diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 57f81f7fd51e..6151bef13d9c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -60,7 +60,7 @@ jobs: runs-on: ubuntu-24.04 env: # List of platforms to exclude by default - EXCLUDED_PLATFORMS: 'alpine-linux-x64' + EXCLUDED_PLATFORMS: 'alpine-linux-x64,macos-x64' outputs: linux-x64: ${{ steps.include.outputs.linux-x64 }} linux-x64-variants: ${{ steps.include.outputs.linux-x64-variants }} diff --git a/doc/testing.html b/doc/testing.html index 648bc8baa6ae..f52f72ac2f7d 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -424,11 +424,29 @@

JCOV

For more fine-grained control, you can pass arbitrary filters to JCov using --with-jcov-filters, and you can specify a specific JDK to instrument using --with-jcov-input-jdk.

+

The resulting coverage is written into +build/$BUILD/test-results/jcov-output/result.xml.

The JCov report is stored in build/$BUILD/test-results/jcov-output/report.

Please note that running with JCov reporting can be very memory intensive.

-

JCOV_DIFF_CHANGESET

+
JCov scales
+

JCov scales make it possible to record which tests cover each part of +the instrumented code. To collect coverage with scales, set +JCOV_SCALES=true, for example:

+
$ make jcov-test TEST=jdk_lang TEST_OPTS="JCOV_SCALES=true"
+

The resulting coverage data contains the association between covered +code and the tests that covered it. A corresponding +testlist.txt file, which contains the test names, is +generated in the same directory.

+

The JCov report displays the names of the tests that cover each +class.

+

Collecting coverage scales forces jtreg tests to be run in +othervm mode, which takes longer than ordinary JCov +collection. The coverage data is also larger because it includes scale +information, and the generated report is larger because it includes test +names.

+
JCOV_DIFF_CHANGESET

While collecting code coverage with JCov, it is also possible to find coverage for only recently changed code. JCOV_DIFF_CHANGESET specifies a source revision. A textual report will be generated showing coverage of diff --git a/doc/testing.md b/doc/testing.md index 1de6c94b679f..e02a9e09d4e7 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -353,11 +353,33 @@ For more fine-grained control, you can pass arbitrary filters to JCov using `--with-jcov-filters`, and you can specify a specific JDK to instrument using `--with-jcov-input-jdk`. +The resulting coverage is written into +`build/$BUILD/test-results/jcov-output/result.xml`. + The JCov report is stored in `build/$BUILD/test-results/jcov-output/report`. Please note that running with JCov reporting can be very memory intensive. -#### JCOV_DIFF_CHANGESET +##### JCov scales + +JCov scales make it possible to record which tests cover each part of the +instrumented code. To collect coverage with scales, set `JCOV_SCALES=true`, +for example: + + $ make jcov-test TEST=jdk_lang TEST_OPTS="JCOV_SCALES=true" + +The resulting coverage data contains the association between covered code and +the tests that covered it. A corresponding `testlist.txt` file, which contains +the test names, is generated in the same directory. + +The JCov report displays the names of the tests that cover each class. + +Collecting coverage scales forces jtreg tests to be run in `othervm` mode, +which takes longer than ordinary JCov collection. The coverage data is also +larger because it includes scale information, and the generated report is +larger because it includes test names. + +##### JCOV_DIFF_CHANGESET While collecting code coverage with JCov, it is also possible to find coverage for only recently changed code. JCOV_DIFF_CHANGESET specifies a source diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 1433ab32e5ce..1013f38baa77 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -45,7 +45,7 @@ ifneq ($(TEST_VM_OPTS), ) endif $(eval $(call ParseKeywordVariable, TEST_OPTS, \ - SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR JCOV JCOV_DIFF_CHANGESET AOT_JDK, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR JCOV JCOV_DIFF_CHANGESET JCOV_SCALES AOT_JDK, \ STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS, \ )) @@ -121,9 +121,21 @@ ifeq ($(TEST_OPTS_JCOV), true) JCOV_SUPPORT_DIR := $(TEST_SUPPORT_DIR)/jcov-support JCOV_GRABBER_LOG := $(JCOV_OUTPUT_DIR)/grabber.log JCOV_RESULT_FILE := $(JCOV_OUTPUT_DIR)/result.xml + JCOV_TESTLIST := $(JCOV_OUTPUT_DIR)/testlist.txt JCOV_REPORT := $(JCOV_OUTPUT_DIR)/report + JCOV_GRABBER_OPTIONS ?= + JCOV_REPGEN_OPTIONS ?= + TEST_OPTS_JCOV_SCALES ?= false JCOV_MEM_OPTIONS := -Xms64m -Xmx4g + ifeq ($(TEST_OPTS_JCOV_SCALES), true) + JCOV_GRABBER_OPTIONS += -scale -mergebyname -outTestList $(JCOV_TESTLIST) + TEST_JOBS := 1 + JTREG_TEST_MODE := othervm + JTREG_VM_OPTIONS += -Djcov.extension=com.sun.tdk.jcov.runtime.TestNameDecorator + JCOV_REPGEN_OPTIONS += -tests $(JCOV_TESTLIST) + endif + # Replace our normal test JDK with the JCov image. JDK_UNDER_TEST := $(JCOV_IMAGE_DIR) @@ -1414,6 +1426,7 @@ ifeq ($(TEST_OPTS_JCOV), true) fi $(JAVA) $(JCOV_VM_OPTS) -jar $(JCOV_HOME)/lib/jcov.jar Grabber -v -t \ $(JCOV_IMAGE_DIR)/template.xml -o $(JCOV_RESULT_FILE) \ + $(JCOV_GRABBER_OPTIONS) \ 1>$(JCOV_GRABBER_LOG) 2>&1 & jcov-start-grabber: jcov-do-start-grabber @@ -1441,6 +1454,7 @@ ifeq ($(TEST_OPTS_JCOV), true) `$(ECHO) $(TOPDIR)/src/*/share/classes/ | $(TR) ' ' ':'` -fmt html \ $(JCOV_MODULES_FILTER) $(JCOV_FILTERS) \ -mainReportTitle "$(JCOV_REPORT_TITLE)" \ + $(JCOV_REPGEN_OPTIONS) \ -o $(JCOV_REPORT) $(JCOV_RESULT_FILE)) TARGETS += jcov-do-start-grabber jcov-start-grabber jcov-stop-grabber \ diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 8f8a7af47fca..04a475c65b63 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -213,6 +213,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], WARNINGS_ENABLE_ADDITIONAL="" WARNINGS_ENABLE_ADDITIONAL_CXX="" WARNINGS_ENABLE_ADDITIONAL_JVM="" + WARNINGS_ENABLE_ADDITIONAL_JDK="-w34189" DISABLED_WARNINGS="4800 5105" CFLAGS_CONVERSION_WARNINGS= ;; @@ -623,8 +624,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], ADLC_LANGSTD_CXXFLAGS="$LANGSTD_CXXFLAGS" # CFLAGS WARNINGS STUFF - WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL" - WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXX" + WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL $WARNINGS_ENABLE_ADDITIONAL_JDK" + WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXX $WARNINGS_ENABLE_ADDITIONAL_JDK" WARNING_CFLAGS_JVM="$WARNINGS_ENABLE_ALL_JVM" # Set some additional per-OS defines. diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 9abc849f0080..aaac824ecddb 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -829,9 +829,18 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_NOCOOPS], AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_PREVIEW], [ - UTIL_ARG_ENABLE(NAME: cds-archive-preview, DEFAULT: true, RESULT: BUILD_CDS_ARCHIVE_PREVIEW, + UTIL_ARG_ENABLE(NAME: cds-archive-preview, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_PREVIEW, DESC: [enable generation of preview CDS archives (requires --enable-cds-archive)], - CHECKING_MSG: [if default CDS archives for preview should be generated]) + CHECKING_MSG: [if default CDS archives for preview should be generated], + CHECK_AVAILABLE: [ + AC_MSG_CHECKING([if value objects are supported]) + if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no (64-bit only)]) + AVAILABLE=false + fi + ]) AC_SUBST(BUILD_CDS_ARCHIVE_PREVIEW) ]) diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 index 28aea489f7ec..cdeae97c8ac8 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.m4 @@ -660,7 +660,19 @@ AC_DEFUN([PLATFORM_CHECK_DEPRECATION], [ AC_ARG_ENABLE(deprecated-ports, [AS_HELP_STRING([--enable-deprecated-ports@<:@=yes/no@:>@], [Suppress the error when configuring for a deprecated port @<:@no@:>@])]) - # There are no deprecated ports. Implement the deprecation warnings here. + if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + # Unfortunately, variants have not been parsed yet, so we have to check the configure option + # directly. Allow only the directly specified Zero variant, treat any other mix as containing + # something non-Zero. + if test "x$with_jvm_variants" != xzero; then + if test "x$enable_deprecated_ports" = "xyes"; then + AC_MSG_WARN([The macOS/x64 port is deprecated and may be removed in a future release.]) + else + AC_MSG_ERROR(m4_normalize([The macOS/x64 port is deprecated and may be removed in a future release. + Use --enable-deprecated-ports to suppress this error.])) + fi + fi + fi ]) AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_BUILD_OS_VERSION], diff --git a/make/common/TestFilesCompilation.gmk b/make/common/TestFilesCompilation.gmk index fd1c54eaf484..dd02d90c537e 100644 --- a/make/common/TestFilesCompilation.gmk +++ b/make/common/TestFilesCompilation.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -118,6 +118,7 @@ define SetupTestFilesCompilationBody DISABLED_WARNINGS_clang := format-nonliteral \ missing-field-initializers sometimes-uninitialized undef \ unused-but-set-variable unused-function unused-variable, \ + DISABLED_WARNINGS_microsoft := 4189, \ DEFAULT_LIBCXX := false, \ JDK_LIBS := $$($1_JDK_LIBS_$$(name)), \ LIBS := $$($1_LIBS) $$($1_LIBS_$$(name)), \ diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 32f07325c058..b83ca709a888 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -416,6 +416,7 @@ var getJibProfilesProfiles = function (input, common, data) { "--with-zlib=system", "--with-macosx-version-max=11.00.00", "--enable-compatible-cds-alignment", + "--enable-deprecated-ports", // Use system SetFile instead of the one in the devkit as the // devkit one may not work on Catalina. "SETFILE=/usr/bin/SetFile" @@ -1192,8 +1193,8 @@ var getJibProfilesDependencies = function (input, common) { server: "jpg", product: "jcov", version: "3.0", - build_number: "6", - file: "bundles/jcov-3.0+6.zip", + build_number: "9", + file: "bundles/jcov-3.0+9.zip", environment_name: "JCOV_HOME", }, diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index bb67474b3a07..50b632a49f91 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -285,13 +285,6 @@ ifeq ($(call isTargetOs, windows), true) $(BUILD_LIBJVM_TARGET): $(WIN_EXPORT_FILE) endif -# Always recompile abstract_vm_version.cpp if libjvm needs to be relinked. This ensures -# that the internal vm version is updated as it relies on __DATE__ and __TIME__ -# macros. -ABSTRACT_VM_VERSION_OBJ := $(JVM_OUTPUTDIR)/objs/abstract_vm_version$(OBJ_SUFFIX) -$(ABSTRACT_VM_VERSION_OBJ): $(filter-out $(ABSTRACT_VM_VERSION_OBJ), \ - $(BUILD_LIBJVM_TARGET_DEPS)) - ifneq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) ifeq ($(call isTargetOs, windows), true) # It doesn't matter which jvm.lib file gets exported, but we need diff --git a/make/modules/java.base/gensrc/GensrcMisc.gmk b/make/modules/java.base/gensrc/GensrcMisc.gmk index edb5e8bc58ef..2c563f4bfd4f 100644 --- a/make/modules/java.base/gensrc/GensrcMisc.gmk +++ b/make/modules/java.base/gensrc/GensrcMisc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,7 @@ else OPENJDK_TARGET_OS_CANONICAL := $(OPENJDK_TARGET_OS) endif -$(eval $(call SetupTextFileProcessing, BUILD_PLATFORMPROPERTIES_JAVA, \ +$(eval $(call SetupTextFileProcessing, BUILD_PLATFORMPROPERTIES_JAVA_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU), \ SOURCE_FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template, \ OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/util/PlatformProps.java, \ REPLACEMENTS := \ @@ -82,7 +82,8 @@ $(eval $(call SetupTextFileProcessing, BUILD_PLATFORMPROPERTIES_JAVA, \ @@OPENJDK_TARGET_CPU_BITS@@ => $(OPENJDK_TARGET_CPU_BITS), \ )) -TARGETS += $(BUILD_VERSION_JAVA) $(BUILD_PLATFORMPROPERTIES_JAVA) +TARGETS += $(BUILD_VERSION_JAVA) \ + $(BUILD_PLATFORMPROPERTIES_JAVA_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)) ################################################################################ ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), ) diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk index 1c43950480c4..9d2a82d60321 100644 --- a/make/modules/java.desktop/Lib.gmk +++ b/make/modules/java.desktop/Lib.gmk @@ -64,10 +64,8 @@ ifeq ($(ENABLE_JSOUND), true) EXTRA_HEADER_DIRS := java.base:libjava, \ CFLAGS := $(LIBJSOUND_CFLAGS), \ CXXFLAGS := $(LIBJSOUND_CFLAGS), \ - DISABLED_WARNINGS_gcc := undef unused-variable, \ - DISABLED_WARNINGS_clang := undef unused-variable, \ - DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_MidiUtils.c := \ - unused-but-set-variable, \ + DISABLED_WARNINGS_gcc := undef, \ + DISABLED_WARNINGS_clang := undef, \ DISABLED_WARNINGS_clang_DirectAudioDevice.c := unused-function, \ LIBS_linux := $(ALSA_LIBS), \ LIBS_macosx := \ diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk index 887dfab01dff..ca98434d3830 100644 --- a/make/modules/java.desktop/lib/AwtLibraries.gmk +++ b/make/modules/java.desktop/lib/AwtLibraries.gmk @@ -134,7 +134,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ DISABLED_WARNINGS_clang_debug_trace.c := format-nonliteral, \ DISABLED_WARNINGS_clang_Trace.c := format-nonliteral, \ DISABLED_WARNINGS_clang_TransformHelper.c := sign-compare, \ - DISABLED_WARNINGS_microsoft := 4244 4996, \ + DISABLED_WARNINGS_microsoft := 4244 4996 4189, \ DISABLED_WARNINGS_microsoft_awt_Toolkit.cpp := 4267, \ LDFLAGS_windows := -delayload:comctl32.dll -delayload:comdlg32.dll \ -delayload:gdi32.dll -delayload:imm32.dll -delayload:ole32.dll \ diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index 2326505d11c2..a09e54ce5ab4 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -343,7 +343,7 @@ else expansion-to-defined dangling-reference maybe-uninitialized HARFBUZZ_DISABLED_WARNINGS_clang := missing-field-initializers \ range-loop-analysis unused-variable - HARFBUZZ_DISABLED_WARNINGS_microsoft := 4267 4244 + HARFBUZZ_DISABLED_WARNINGS_microsoft := 4267 4244 4189 LIBFONTMANAGER_CFLAGS += $(HARFBUZZ_CFLAGS) endif diff --git a/src/hotspot/cpu/aarch64/bytes_aarch64.hpp b/src/hotspot/cpu/aarch64/bytes_aarch64.hpp deleted file mode 100644 index 6d4a18d00b5f..000000000000 --- a/src/hotspot/cpu/aarch64/bytes_aarch64.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 1997, 2022, 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. - * - * 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 CPU_AARCH64_BYTES_AARCH64_HPP -#define CPU_AARCH64_BYTES_AARCH64_HPP - -#include "memory/allStatic.hpp" -#include "utilities/byteswap.hpp" - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - // (no special code is needed since x86 CPUs can access unaligned data) - static inline u2 get_native_u2(address p) { return *(u2*)p; } - static inline u4 get_native_u4(address p) { return *(u4*)p; } - static inline u8 get_native_u8(address p) { return *(u8*)p; } - - static inline void put_native_u2(address p, u2 x) { *(u2*)p = x; } - static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; } - static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; } - - - // Efficient reading and writing of unaligned unsigned data in Java - // byte ordering (i.e. big-endian ordering). Byte-order reversal is - // needed since x86 CPUs use little-endian format. - static inline u2 get_Java_u2(address p) { return byteswap(get_native_u2(p)); } - static inline u4 get_Java_u4(address p) { return byteswap(get_native_u4(p)); } - static inline u8 get_Java_u8(address p) { return byteswap(get_native_u8(p)); } - - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, byteswap(x)); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, byteswap(x)); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, byteswap(x)); } -}; - -#endif // CPU_AARCH64_BYTES_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index d05526890cba..9a35a01c4d2d 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -1569,13 +1569,8 @@ void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // We are storing into an array that *may* be null-free (the declared type is // Object[], abstract[], interface[] or VT.ref[]). - Label test_mark_word; Register tmp = op->tmp()->as_register(); __ ldr(tmp, Address(op->array()->as_register(), oopDesc::mark_offset_in_bytes())); - __ tst(tmp, markWord::unlocked_value); - __ br(Assembler::NE, test_mark_word); - __ load_prototype_header(tmp, op->array()->as_register()); - __ bind(test_mark_word); __ tst(tmp, markWord::null_free_array_bit_in_place); } diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index fba316bf293e..96a4f4d3daaf 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -221,8 +221,8 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1, assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea"); // Try to lock. Transition lock-bits 0b01 => 0b00 - orr(t1_mark, t1_mark, markWord::unlocked_value); - eor(t3_t, t1_mark, markWord::unlocked_value); + orr(t1_mark, t1_mark, markWord::lock_neutral_value); + eor(t3_t, t1_mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_acquire); br(Assembler::NE, slow_path); @@ -383,7 +383,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register box, Register t1, // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); - orr(t3_t, t1_mark, markWord::unlocked_value); + orr(t3_t, t1_mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_release); br(Assembler::EQ, unlocked); diff --git a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp index 97d9f7afdfb4..9c8c7393354d 100644 --- a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -37,7 +38,7 @@ void CodeBuffer::share_trampoline_for(address dest, int caller_offset) { if (created) { _shared_trampoline_requests->maybe_grow(); } - offsets->add(caller_offset); + offsets->push(caller_offset); _finalize_stubs = true; } @@ -50,16 +51,19 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline MacroAssembler masm(cb); - auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) { + auto emit = [&](address dest, const CodeBuffer::Offsets& offsets) { assert(cb->stubs()->remaining() >= MacroAssembler::max_trampoline_stub_size(), "pre-allocated trampolines"); - LinkedListIterator it(offsets.head()); - int offset = *it.next(); + assert(offsets.length() > 0, "must be"); + // We go backwards + const int offset_end = offsets.length() - 1; + int offset = offsets.at(offset_end); address stub = __ emit_trampoline_stub(offset, dest); assert(stub, "pre-allocated trampolines"); address reloc_pc = cb->stubs()->end() - NativeCallTrampolineStub::instruction_size; - while (!it.is_empty()) { - offset = *it.next(); + // Skip the first one + for (int i = offset_end - 1; i >= 0; i--) { + offset = offsets.at(i); address caller_pc = cb->insts()->start() + offset; cb->stubs()->relocate(reloc_pc, trampoline_stub_Relocation::spec(caller_pc)); } diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index 7cc2a004c40d..7d9acafddc09 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -98,25 +98,6 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size result = reserve_at_eor_compatible_address(size, aslr); } - // Movk-compatible reservation via probing. - if (result == nullptr) { - result = reserve_address_space_for_16bit_move(size, aslr); - } - - // Movk-compatible reservation via overallocation. - // If that failed, attempt to allocate at any 4G-aligned address. Let the system decide where. For ASLR, - // we now rely on the system. - // Compared with the probing done above, this has two disadvantages: - // - on a kernel with 52-bit address space we may get an address that has bits set between [48, 52). - // In that case, we may need two movk moves (not yet implemented). - // - this technique leads to temporary over-reservation of address space; it will spike the vsize of - // the process. Therefore it may fail if a vsize limit is in place (e.g. ulimit -v). - if (result == nullptr) { - constexpr size_t alignment = nth_bit(32); - log_debug(metaspace, map)("Trying to reserve at a 32-bit-aligned address"); - result = os::reserve_memory_aligned(size, alignment, mtNone); - } - return result; } diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index db0d5e007a02..766b2b4dda0a 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -308,8 +308,10 @@ void DowncallLinker::StubGenerator::generate() { // Restore cpu control state after JNI call __ restore_cpu_control_state_after_jni(rscratch1, tmp1); - __ mov(tmp1, _thread_in_vm); - __ strw(tmp1, Address(rthread, JavaThread::thread_state_offset())); + // change thread state + __ mov(tmp1, _thread_in_Java); + __ lea(tmp2, Address(rthread, JavaThread::thread_state_offset())); + __ stlrw(tmp1, tmp2); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -326,11 +328,6 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_after_safepoint_poll); - // change thread state - __ mov(tmp1, _thread_in_Java); - __ lea(tmp2, Address(rthread, JavaThread::thread_state_offset())); - __ stlrw(tmp1, tmp2); - __ block_comment("reguard stack check"); __ ldrb(tmp1, Address(rthread, JavaThread::stack_guard_state_offset())); __ cmpw(tmp1, StackOverflow::stack_guard_yellow_reserved_disabled); @@ -356,7 +353,7 @@ void DowncallLinker::StubGenerator::generate() { __ mov(c_rarg0, rthread); assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); - __ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + __ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans))); __ blr(tmp1); if (should_save_return_value) { @@ -388,5 +385,5 @@ void DowncallLinker::StubGenerator::generate() { ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. } diff --git a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad index 74e0395c81ec..11b70e4e8384 100644 --- a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad +++ b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad @@ -33,14 +33,14 @@ source %{ #include "gc/z/zBarrierSetAssembler.hpp" -static void z_color(MacroAssembler* masm, const MachNode* node, Register dst, Register src) { +static void z_color(MacroAssembler* masm, Register dst, Register src) { assert_different_registers(src, dst); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodBeforeMov); __ movzw(dst, barrier_Relocation::unpatched); __ orr(dst, dst, src, Assembler::LSL, ZPointerLoadShift); } -static void z_uncolor(MacroAssembler* masm, const MachNode* node, Register ref) { +static void z_uncolor(MacroAssembler* masm, Register ref) { __ lsr(ref, ref, ZPointerLoadShift); } @@ -50,7 +50,7 @@ static void z_keep_alive_load_barrier(MacroAssembler* masm, const MachNode* node __ tst(ref, tmp); ZLoadBarrierStubC2Aarch64* const stub = ZLoadBarrierStubC2Aarch64::create(node, ref_addr, ref); __ br(Assembler::NE, *stub->entry()); - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); __ bind(*stub->continuation()); } @@ -66,7 +66,7 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r } if (node->barrier_data() == ZBarrierElided) { - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); return; } @@ -81,14 +81,14 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r __ b(*stub->entry()); __ bind(good); } - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); __ bind(*stub->continuation()); } static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) { Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); if (node->barrier_data() == ZBarrierElided) { - z_color(masm, node, rnew_zpointer, rnew_zaddress); + z_color(masm, rnew_zpointer, rnew_zaddress); } else { bool is_native = (node->barrier_data() & ZBarrierNative) != 0; bool is_nokeepalive = (node->barrier_data() & ZBarrierNoKeepalive) != 0; @@ -206,7 +206,7 @@ instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newva guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_release); __ cset($res$$Register, Assembler::EQ); %} @@ -229,7 +229,7 @@ instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_seq_cst); __ cset($res$$Register, Assembler::EQ); %} @@ -251,10 +251,10 @@ instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP n guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_release, $res$$Register); - z_uncolor(masm, this, $res$$Register); + z_uncolor(masm, $res$$Register); %} ins_pipe(pipe_slow); @@ -274,10 +274,10 @@ instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iReg guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_seq_cst, $res$$Register); - z_uncolor(masm, this, $res$$Register); + z_uncolor(masm, $res$$Register); %} ins_pipe(pipe_slow); @@ -295,7 +295,7 @@ instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ ins_encode %{ z_store_barrier(masm, this, Address($mem$$Register), $newv$$Register, $prev$$Register, rscratch2, true /* is_atomic */); __ atomic_xchg($prev$$Register, $prev$$Register, $mem$$Register); - z_uncolor(masm, this, $prev$$Register); + z_uncolor(masm, $prev$$Register); %} ins_pipe(pipe_serial); @@ -313,7 +313,7 @@ instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) ins_encode %{ z_store_barrier(masm, this, Address($mem$$Register), $newv$$Register, $prev$$Register, rscratch2, true /* is_atomic */); __ atomic_xchgal($prev$$Register, $prev$$Register, $mem$$Register); - z_uncolor(masm, this, $prev$$Register); + z_uncolor(masm, $prev$$Register); %} ins_pipe(pipe_serial); diff --git a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp index c9daef8c6cfa..a92f8f5014cb 100644 --- a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -181,7 +181,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin __ lea(r0, ExternalAddress(Interpreter::result_handler(method()->result_type()))); __ ret(lr); - __ flush(); + __ invalidate_icache(); } diff --git a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp index cffdcf494296..8fd1ffca14cb 100644 --- a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -206,7 +206,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { __ leave(); __ ret(lr); } - __ flush (); + __ invalidate_icache(); return fast_entry; } diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 6d280d9e8ab9..74fd6e0d42af 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -5318,12 +5318,6 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi cmpw(tmp1, tmp2); } -void MacroAssembler::load_prototype_header(Register dst, Register src) { - Register tmp = (dst == rscratch1) ? rscratch2 : rscratch1; - load_klass(dst, src, tmp); - ldr(dst, Address(dst, Klass::prototype_header_offset())); -} - void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { // FIXME: Should this be a store release? concurrent gcs assumes // klass length is valid if klass field is not null. @@ -5494,12 +5488,6 @@ MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, } } - const uint64_t shifted_base = - (uint64_t)base >> shift; - if ((shifted_base & 0xffff0000ffffffff) == 0) { - return KlassDecodeMovk; - } - return KlassDecodeFallback; } @@ -5545,14 +5533,6 @@ void MacroAssembler::emit_encode_klass_not_null(Register dst, Register src, Regi lsr(dst, dst, shift); break; - case KlassDecodeMovk: - if (shift != 0) { - ubfx(dst, src, shift, 32); - } else { - movw(dst, src); - } - break; - case KlassDecodeFallback: { mov(tmp, base); sub(dst, src, tmp); @@ -5609,16 +5589,6 @@ void MacroAssembler::emit_decode_klass_not_null(Register dst, Register src, Regi eor(dst, dst, (uint64_t)base); break; - case KlassDecodeMovk: { // 1-3 instructions - const uint64_t shifted_base = - (uint64_t)base >> shift; - - if (dst != src) movw(dst, src); - movk(dst, shifted_base >> 32, 32); - lsl(dst, dst, shift); - break; - } - case KlassDecodeFallback: { // 3-4 instructions mov(tmp, base); add(dst, tmp, src, LSL, shift); @@ -7920,13 +7890,13 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register t1, R // Try to lock. Transition lock bits 0b01 => 0b00 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); - orr(mark, mark, markWord::unlocked_value); + orr(mark, mark, markWord::lock_neutral_value); if (Arguments::is_valhalla_enabled()) { // Mask inline_type bit such that we go to the slow path if object is an inline type andr(mark, mark, ~((int) markWord::inline_type_bit_in_place)); } - eor(t, mark, markWord::unlocked_value); + eor(t, mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword, memory_order_acquire); br(Assembler::NE, slow); @@ -7985,16 +7955,16 @@ void MacroAssembler::fast_unlock(Register obj, Register t1, Register t2, Registe tbnz(mark, log2i_exact(markWord::monitor_value), push_and_slow); #ifdef ASSERT - // Check header not unlocked (0b01). + // Check header not unlocked / lock-neutral (0b01). Label not_unlocked; - tbz(mark, log2i_exact(markWord::unlocked_value), not_unlocked); + tbz(mark, log2i_exact(markWord::lock_neutral_value), not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); #endif // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); - orr(t, mark, markWord::unlocked_value); + orr(t, mark, markWord::lock_neutral_value); cmpxchg(obj, mark, t, Assembler::xword, memory_order_release); br(Assembler::EQ, unlocked); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 826f88fe85c3..ba46983c7a07 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -104,7 +104,6 @@ class MacroAssembler: public Assembler { KlassDecodeNone, KlassDecodeZero, KlassDecodeXor, - KlassDecodeMovk, KlassDecodeFallback }; @@ -1000,8 +999,6 @@ class MacroAssembler: public Assembler { // stored using routines that take a jobject. void store_heap_oop_null(Address dst); - void load_prototype_header(Register dst, Register src); - void store_klass_gap(Register dst, Register src); // This dummy is to prevent a call to store_heap_oop from diff --git a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp index 638e57b03fee..9620aba88f8c 100644 --- a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, 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. * @@ -249,8 +249,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Jump to interpreter __ ret(lr); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); @@ -391,8 +390,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ br(r8); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Set exception blob ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); @@ -400,5 +398,3 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { return ex_blob; } #endif // COMPILER2 - - diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 60065ab19406..e2b8e1a1ed94 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1612,7 +1612,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, assert(vep_offset != -1, "Must be set"); #endif - __ flush(); + // Code will be copied. No ICache sync required. nmethod* nm = nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -1646,7 +1646,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, in_sig_bt, in_regs); int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period - __ flush(); + // Code will be copied. No ICache sync required. int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually return nmethod::new_native_nmethod(method, compile_id, @@ -2047,9 +2047,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, Label safepoint_in_progress, safepoint_in_progress_done; - __ mov(rscratch1, _thread_in_vm); - - __ strw(rscratch1, Address(rthread, JavaThread::thread_state_offset())); + // change thread state + __ mov(rscratch1, _thread_in_Java); + __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset())); + __ stlrw(rscratch1, rscratch2); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -2067,11 +2068,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ bind(safepoint_in_progress_done); } - // change thread state - __ mov(rscratch1, _thread_in_Java); - __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset())); - __ stlrw(rscratch1, rscratch2); - if (method->is_object_wait0()) { // Check preemption for Object.wait() __ ldr(rscratch1, Address(rthread, JavaThread::preempt_alternate_return_offset())); @@ -2273,7 +2269,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, #ifndef PRODUCT assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); #endif - __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans))); __ blr(rscratch1); // Restore any method result value @@ -2316,7 +2312,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } } - __ flush(); + // Code will be copied. No ICache sync required. nmethod *nm = nmethod::new_native_nmethod(method, compile_id, @@ -2657,8 +2653,7 @@ void SharedRuntime::generate_deopt_blob() { // Jump to interpreter __ ret(lr); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); @@ -2806,8 +2801,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ stop("Attempting to adjust pc to skip safepoint poll but the return point is not what we expected"); #endif - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Fill-out other meta info SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); @@ -2902,9 +2896,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ ldr(r0, Address(rthread, Thread::pending_exception_offset())); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // return the blob // frame_size_words or bytes?? @@ -3058,7 +3050,7 @@ BufferedInlineTypeBlob* SharedRuntime::generate_buffered_inline_type_adapter(con __ ret(lr); - __ flush(); + // Code will be copied. No ICache sync required. return BufferedInlineTypeBlob::create(&buffer, pack_fields_off, pack_fields_jobject_off, unpack_fields_off); } @@ -3309,9 +3301,7 @@ RuntimeStub* SharedRuntime::generate_return_value_stub(address destination) { __ leave(); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &code, frame_complete, frame_size_in_words, oop_maps, false); AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 9c53800dd34b..c317629d6cc9 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1422,7 +1422,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ verify_sve_vector_length(); // change thread state - __ mov(rscratch1, _thread_in_vm); + __ mov(rscratch1, _thread_in_Java); __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset())); __ stlrw(rscratch1, rscratch2); @@ -1447,18 +1447,13 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // hand. // __ mov(c_rarg0, rthread); - __ lea(rscratch2, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + __ lea(rscratch2, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans))); __ blr(rscratch2); __ get_method(rmethod); __ reinit_heapbase(); __ bind(Continue); } - // change thread state - __ mov(rscratch1, _thread_in_Java); - __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset())); - __ stlrw(rscratch1, rscratch2); - // Check preemption for Object.wait() Label not_preempted; __ ldr(rscratch1, Address(rthread, JavaThread::preempt_alternate_return_offset())); diff --git a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp index 7a0e5aaf3b4e..7f678317a9da 100644 --- a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2022, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -310,7 +310,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, ////////////////////////////////////////////////////////////////////////////// - _masm->flush(); + // Code will be copied. No ICache sync required. #ifndef PRODUCT stringStream ss; diff --git a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp index a070b4f66024..c81bf733a1fb 100644 --- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, 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. * @@ -132,7 +132,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) __ ldr(rscratch1, Address(rmethod, entry_offset)); __ br(rscratch1); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); return s; @@ -233,7 +233,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) assert(SharedRuntime::get_handle_wrong_method_stub() != nullptr, "check initialization order"); __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); return s; diff --git a/src/hotspot/cpu/arm/bytes_arm.hpp b/src/hotspot/cpu/arm/bytes_arm.hpp deleted file mode 100644 index 6ebf5a61e4f7..000000000000 --- a/src/hotspot/cpu/arm/bytes_arm.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 CPU_ARM_BYTES_ARM_HPP -#define CPU_ARM_BYTES_ARM_HPP - -#include "memory/allStatic.hpp" -#include "utilities/macros.hpp" - -#ifndef VM_LITTLE_ENDIAN -#define VM_LITTLE_ENDIAN 1 -#endif - -class Bytes: AllStatic { - - public: - static inline u2 get_Java_u2(address p) { - return (u2(p[0]) << 8) | u2(p[1]); - } - - static inline u4 get_Java_u4(address p) { - return u4(p[0]) << 24 | - u4(p[1]) << 16 | - u4(p[2]) << 8 | - u4(p[3]); - } - - static inline u8 get_Java_u8(address p) { - return u8(p[0]) << 56 | - u8(p[1]) << 48 | - u8(p[2]) << 40 | - u8(p[3]) << 32 | - u8(p[4]) << 24 | - u8(p[5]) << 16 | - u8(p[6]) << 8 | - u8(p[7]); - } - - static inline void put_Java_u2(address p, u2 x) { - p[0] = x >> 8; - p[1] = x; - } - - static inline void put_Java_u4(address p, u4 x) { - ((u1*)p)[0] = x >> 24; - ((u1*)p)[1] = x >> 16; - ((u1*)p)[2] = x >> 8; - ((u1*)p)[3] = x; - } - - static inline void put_Java_u8(address p, u8 x) { - ((u1*)p)[0] = x >> 56; - ((u1*)p)[1] = x >> 48; - ((u1*)p)[2] = x >> 40; - ((u1*)p)[3] = x >> 32; - ((u1*)p)[4] = x >> 24; - ((u1*)p)[5] = x >> 16; - ((u1*)p)[6] = x >> 8; - ((u1*)p)[7] = x; - } - -#ifdef VM_LITTLE_ENDIAN - - static inline u2 get_native_u2(address p) { - return (intptr_t(p) & 1) == 0 ? *(u2*)p : u2(p[0]) | (u2(p[1]) << 8); - } - - static inline u4 get_native_u4(address p) { - switch (intptr_t(p) & 3) { - case 0: return *(u4*)p; - case 2: return u4(((u2*)p)[0]) | - u4(((u2*)p)[1]) << 16; - default: return u4(p[0]) | - u4(p[1]) << 8 | - u4(p[2]) << 16 | - u4(p[3]) << 24; - } - } - - static inline u8 get_native_u8(address p) { - switch (intptr_t(p) & 7) { - case 0: return *(u8*)p; - case 4: return u8(((u4*)p)[0]) | - u8(((u4*)p)[1]) << 32; - case 2: return u8(((u2*)p)[0]) | - u8(((u2*)p)[1]) << 16 | - u8(((u2*)p)[2]) << 32 | - u8(((u2*)p)[3]) << 48; - default: return u8(p[0]) | - u8(p[1]) << 8 | - u8(p[2]) << 16 | - u8(p[3]) << 24 | - u8(p[4]) << 32 | - u8(p[5]) << 40 | - u8(p[6]) << 48 | - u8(p[7]) << 56; - } - } - - static inline void put_native_u2(address p, u2 x) { - if ((intptr_t(p) & 1) == 0) { - *(u2*)p = x; - } else { - p[0] = x; - p[1] = x >> 8; - } - } - - static inline void put_native_u4(address p, u4 x) { - switch (intptr_t(p) & 3) { - case 0: *(u4*)p = x; - break; - case 2: ((u2*)p)[0] = x; - ((u2*)p)[1] = x >> 16; - break; - default: ((u1*)p)[0] = x; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[3] = x >> 24; - break; - } - } - - static inline void put_native_u8(address p, u8 x) { - switch (intptr_t(p) & 7) { - case 0: *(u8*)p = x; - break; - case 4: ((u4*)p)[0] = x; - ((u4*)p)[1] = x >> 32; - break; - case 2: ((u2*)p)[0] = x; - ((u2*)p)[1] = x >> 16; - ((u2*)p)[2] = x >> 32; - ((u2*)p)[3] = x >> 48; - break; - default: ((u1*)p)[0] = x; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[3] = x >> 24; - ((u1*)p)[4] = x >> 32; - ((u1*)p)[5] = x >> 40; - ((u1*)p)[6] = x >> 48; - ((u1*)p)[7] = x >> 56; - } - } - -#else - - static inline u2 get_native_u2(address p) { return get_Java_u2(p); } - static inline u4 get_native_u4(address p) { return get_Java_u4(p); } - static inline u8 get_native_u8(address p) { return get_Java_u8(p); } - static inline void put_native_u2(address p, u2 x) { put_Java_u2(p, x); } - static inline void put_native_u4(address p, u4 x) { put_Java_u4(p, x); } - static inline void put_native_u8(address p, u8 x) { put_Java_u8(p, x); } - -#endif // VM_LITTLE_ENDIAN -}; - -#endif // CPU_ARM_BYTES_ARM_HPP diff --git a/src/hotspot/cpu/arm/jniFastGetField_arm.cpp b/src/hotspot/cpu/arm/jniFastGetField_arm.cpp index 3a5dd10e82eb..fc7e439effa2 100644 --- a/src/hotspot/cpu/arm/jniFastGetField_arm.cpp +++ b/src/hotspot/cpu/arm/jniFastGetField_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,11 @@ #include "asm/macroAssembler.hpp" #include "code/codeBlob.hpp" #include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "prims/jvmtiExport.hpp" +#include "runtime/jfieldIDWorkaround.hpp" #include "runtime/jniHandles.hpp" #include "runtime/safepoint.hpp" @@ -138,10 +140,10 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { #endif // !__ABI_HARD__ ) { // Only ldr and ldrb support embedded shift, other loads do not - __ add(Robj, Robj, AsmOperand(R2, lsr, 2)); + __ add(Robj, Robj, AsmOperand(R2, lsr, jfieldIDWorkaround::offset_shift)); field_addr = Address(Robj); } else { - field_addr = Address(Robj, R2, lsr, 2); + field_addr = Address(Robj, R2, lsr, jfieldIDWorkaround::offset_shift); } assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); speculative_load_pclist[count] = __ pc(); @@ -210,7 +212,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { __ bind_literal(safepoint_counter_addr); - __ flush(); + __ invalidate_icache(); guarantee((__ pc() - fast_entry) <= BUFFER_SIZE, "BUFFER_SIZE too small"); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 6715effa68fd..ce79fc57ccd4 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -1780,7 +1780,7 @@ void MacroAssembler::fast_lock(Register obj, Register t1, Register t2, Register Register new_hdr = t2; ldr(new_hdr, Address(obj, oopDesc::mark_offset_in_bytes())); bic(new_hdr, new_hdr, markWord::lock_mask_in_place); // new header (00) - orr(old_hdr, new_hdr, markWord::unlocked_value); // old header (01) + orr(old_hdr, new_hdr, markWord::lock_neutral_value); // old header (01) Label dummy; @@ -1829,7 +1829,7 @@ void MacroAssembler::fast_unlock(Register obj, Register t1, Register t2, Registe Register new_hdr = t2; ldr(old_hdr, Address(obj, oopDesc::mark_offset_in_bytes())); bic(old_hdr, old_hdr, markWord::lock_mask_in_place); // old header (00) - orr(new_hdr, old_hdr, markWord::unlocked_value); // new header (01) + orr(new_hdr, old_hdr, markWord::lock_neutral_value); // new header (01) // Try to swing header from locked to unlocked Label dummy; diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp index 3119c7141b1f..59c13e05ef6f 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -449,7 +449,7 @@ class MacroAssembler: public Assembler { int should_not_call_this() { raw_push(FP, LR); should_not_reach_here(); - flush(); + invalidate_icache(); return 2; // frame_size_in_words (FP+LR) } diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp index 29fd0aa0a103..5a1845ac0593 100644 --- a/src/hotspot/cpu/arm/runtime_arm.cpp +++ b/src/hotspot/cpu/arm/runtime_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -176,7 +176,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { __ mov(SP, FP); __ pop(RegisterSet(FP) | RegisterSet(PC)); - masm->flush(); + masm->invalidate_icache(); return UncommonTrapBlob::create(&buffer, nullptr, 2 /* LR+FP */); } @@ -280,7 +280,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // ------------- // make sure all code is generated - masm->flush(); + masm->invalidate_icache(); return ExceptionBlob::create(&buffer, oop_maps, framesize_in_words); } diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 593ba159aa7b..ed4d9c8f2e73 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -850,7 +850,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, in_sig_bt, in_regs); int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period - __ flush(); + __ invalidate_icache(); int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually return nmethod::new_native_nmethod(method, compile_id, @@ -938,8 +938,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ ldr(Rtemp, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - assert(markWord::unlocked_value == 1, "adjust this code"); - __ tbz(Rtemp, exact_log2(markWord::unlocked_value), slow_case); + assert(markWord::lock_neutral_value == 1, "adjust this code"); + __ tbz(Rtemp, exact_log2(markWord::lock_neutral_value), slow_case); __ bics(Rtemp, Rtemp, ~markWord::hash_mask_in_place); __ mov(R0, AsmOperand(Rtemp, lsr, markWord::hash_shift), ne); @@ -1263,9 +1263,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ c2bool(R0); } - // Do a safepoint check + // Perform thread state transition Label call_safepoint_runtime, return_to_java; - __ mov(Rtemp, _thread_in_vm); + __ mov(Rtemp, _thread_in_Java); __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset())); // make sure the store is observed before reading the SafepointSynchronize state and further mem refs @@ -1273,6 +1273,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad | MacroAssembler::StoreStore), Rtemp); } + // Do a safepoint check __ safepoint_poll(R2, call_safepoint_runtime); __ ldr_u32(R3, Address(Rthread, JavaThread::suspend_flags_offset())); __ cmp(R3, 0); @@ -1280,12 +1281,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ bind(return_to_java); - // Perform thread state transition and reguard stack yellow pages if needed + // Reguard stack yellow pages if needed Label reguard, reguard_done; - __ mov(Rtemp, _thread_in_Java); __ ldr_s32(R2, Address(Rthread, JavaThread::stack_guard_state_offset())); - __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset())); - __ cmp(R2, StackOverflow::stack_guard_yellow_reserved_disabled); __ b(reguard, eq); __ bind(reguard_done); @@ -1336,7 +1334,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ bind(call_safepoint_runtime); push_result_registers(masm, ret_type); __ mov(R0, Rthread); - __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ call(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); pop_result_registers(masm, ret_type); __ b(return_to_java); @@ -1385,7 +1383,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ b(unlock_done); } - __ flush(); + __ invalidate_icache(); return nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -1654,7 +1652,7 @@ void SharedRuntime::generate_deopt_blob() { __ pop(RegisterSet(FP) | RegisterSet(PC)); - __ flush(); + __ invalidate_icache(); _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); @@ -1734,7 +1732,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); - __ flush(); + __ invalidate_icache(); return SafepointBlob::create(&buffer, oop_maps, frame_size_words); } @@ -1794,7 +1792,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ mov(Rexception_pc, LR); __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); - __ flush(); + __ invalidate_icache(); return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_words, oop_maps, true); } diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index 99f30a8f2669..b7e055b317b9 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1013,8 +1013,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ restore_default_fp_mode(); } - // Do safepoint check - __ mov(Rtemp, _thread_in_vm); + // Perform Native->Java thread transition + __ mov(Rtemp, _thread_in_Java); __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset())); // Force this write out before the read below @@ -1033,6 +1033,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { saved_result_fp = fnoreg; #endif // __ABI_HARD__ + // Do safepoint check { Label call, skip_call; __ safepoint_poll(Rtemp, call); @@ -1041,7 +1042,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ b(skip_call, eq); __ bind(call); __ mov(R0, Rthread); - __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), relocInfo::none); + __ call(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans), relocInfo::none); __ bind(skip_call); #if R9_IS_SCRATCHED @@ -1049,10 +1050,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { #endif } - // Perform Native->Java thread transition - __ mov(Rtemp, _thread_in_Java); - __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset())); - // Zero handles and last_java_sp __ reset_last_Java_frame(Rtemp); __ ldr(R3, Address(Rthread, JavaThread::active_handles_offset())); diff --git a/src/hotspot/cpu/arm/vtableStubs_arm.cpp b/src/hotspot/cpu/arm/vtableStubs_arm.cpp index 80b3cb3a400f..3f34fa76969e 100644 --- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp +++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp @@ -110,7 +110,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) address ame_addr = __ pc(); __ ldr(PC, Address(Rmethod, Method::from_compiled_offset())); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); return s; @@ -205,7 +205,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) assert(SharedRuntime::get_handle_wrong_method_stub() != nullptr, "check initialization order"); __ jump(SharedRuntime::get_handle_wrong_method_stub(), relocInfo::runtime_call_type, Rtemp); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); return s; diff --git a/src/hotspot/cpu/ppc/assembler_ppc.hpp b/src/hotspot/cpu/ppc/assembler_ppc.hpp index 77c7f63cd062..87c12f3e4ed5 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp @@ -539,6 +539,10 @@ class Assembler : public AbstractAssembler { STXVL_OPCODE = (31u << OPCODE_SHIFT | 397u << 1), LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1), STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1), + LXVW4X_OPCODE = (31u << OPCODE_SHIFT | 780u << 1), + STXVW4X_OPCODE = (31u << OPCODE_SHIFT | 908u << 1), + LXVB16X_OPCODE = (31u << OPCODE_SHIFT | 876u << 1), + STXVB16X_OPCODE= (31u << OPCODE_SHIFT | 1004u << 1), MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1), MTVSRDD_OPCODE = (31u << OPCODE_SHIFT | 435u << 1), MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 243u << 1), @@ -1365,10 +1369,6 @@ class Assembler : public AbstractAssembler { return (0 == addr % a); } - void flush() { - AbstractAssembler::flush(); - } - inline void emit_int32(int); // shadows AbstractAssembler::emit_int32 inline void emit_data(int); inline void emit_data(int, RelocationHolder const&); @@ -2386,8 +2386,17 @@ class Assembler : public AbstractAssembler { inline void lxvd2x( VectorSRegister d, Register a, Register b); inline void stxvd2x( VectorSRegister d, Register a); inline void stxvd2x( VectorSRegister d, Register a, Register b); + inline void lxvw4x( VectorSRegister d, Register a); + inline void lxvw4x( VectorSRegister d, Register a, Register b); + inline void stxvw4x( VectorSRegister d, Register a); + inline void stxvw4x( VectorSRegister d, Register a, Register b); // Power9 + inline void lxvb16x( VectorSRegister d, Register a); + inline void lxvb16x( VectorSRegister d, Register a, Register b); + inline void stxvb16x( VectorSRegister d, Register a); + inline void stxvb16x( VectorSRegister d, Register a, Register b); + inline void lxv( VectorSRegister d, int si16, Register a); inline void stxv( VectorSRegister d, int si16, Register a); inline void lxvx( VectorSRegister d, Register a, Register b); @@ -2590,6 +2599,15 @@ class Assembler : public AbstractAssembler { inline void vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm); inline void vec_perm(VectorRegister dest, VectorRegister first, VectorRegister second, VectorRegister perm); + // Load/Store unaligned vectors with offs (multiple of 16). Byte versions require vp for Power8 LE. + inline void load_byte_vector_unaligned(VectorRegister dest, int offs, Register base, Register tmp, + VectorRegister vp); // vp should be pre-computed (see generator below) + inline void store_byte_vector_unaligned(VectorRegister val, int offs, Register base, Register tmp, + VectorRegister vp, VectorRegister vtmp = vnoreg); // clobbers val if no vtmp provided + inline void compute_vp_for_byte_vector_unaligned(VectorRegister dest, VectorRegister vtmp); + inline void load_word_vector_unaligned(VectorRegister dest, int offs, Register base, Register tmp); + inline void store_word_vector_unaligned(VectorRegister val, int offs, Register base, Register tmp); + // RegisterOrConstant versions. // These emitters choose between the versions using two registers and // those with register and immediate, depending on the content of roc. diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp index 22b9e268dcdf..7929e895923b 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp @@ -856,6 +856,14 @@ inline void Assembler::lxvd2x( VectorSRegister d, Register s1) { e inline void Assembler::lxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } inline void Assembler::stxvd2x( VectorSRegister d, Register s1) { emit_int32( STXVD2X_OPCODE | vsrs(d) | ra(0) | rb(s1)); } inline void Assembler::stxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrs(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lxvw4x( VectorSRegister d, Register s1) { emit_int32( LXVW4X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } +inline void Assembler::lxvw4x( VectorSRegister d, Register s1, Register s2) { emit_int32( LXVW4X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stxvw4x( VectorSRegister d, Register s1) { emit_int32( STXVW4X_OPCODE | vsrs(d) | ra(0) | rb(s1)); } +inline void Assembler::stxvw4x( VectorSRegister d, Register s1, Register s2) { emit_int32( STXVW4X_OPCODE | vsrs(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lxvb16x( VectorSRegister d, Register s1) { emit_int32( LXVB16X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } +inline void Assembler::lxvb16x( VectorSRegister d, Register s1, Register s2) { emit_int32( LXVB16X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stxvb16x(VectorSRegister d, Register s1) { emit_int32( STXVB16X_OPCODE| vsrs(d) | ra(0) | rb(s1)); } +inline void Assembler::stxvb16x(VectorSRegister d, Register s1, Register s2) { emit_int32( STXVB16X_OPCODE| vsrs(d) | ra0mem(s1) | rb(s2)); } inline void Assembler::mtvsrd( VectorSRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vsrt(d) | ra(a)); } inline void Assembler::mtvsrdd( VectorSRegister d, Register a, Register b) { emit_int32( MTVSRDD_OPCODE | vsrt(d) | ra(a) | rb(b)); } inline void Assembler::mfvsrd( Register d, VectorSRegister a) { emit_int32( MFVSRD_OPCODE | vsrs(a) | ra(d)); } @@ -1232,6 +1240,108 @@ inline void Assembler::vec_perm(VectorRegister dest, VectorRegister first, Vecto #endif } +inline void Assembler::load_byte_vector_unaligned(VectorRegister dest, int offs, Register base, Register tmp, + VectorRegister vp) { + VectorSRegister vsr = dest->to_vsr(); + if (PowerArchitecturePPC64 >= 9) { +#if !defined(VM_LITTLE_ENDIAN) + lxv(vsr, offs, base); // all vector load/store instructions use the same byte order on BE +#else + if (offs == 0) { + lxvb16x(vsr, base); + } else { + li(tmp, offs); + lxvb16x(vsr, base, tmp); + } +#endif + } else { // Power8 only supports very limited instructions + if (offs == 0) { + lxvd2x(vsr, base); + } else { + li(tmp, offs); + lxvd2x(vsr, base, tmp); + } +#if defined(VM_LITTLE_ENDIAN) + // need to swap bytes in both double-words + vperm(dest, dest, dest, vp); +#endif + } +} + +inline void Assembler::store_byte_vector_unaligned(VectorRegister val, int offs, Register base, Register tmp, + VectorRegister vp, VectorRegister vtmp) { + VectorSRegister vsr = val->to_vsr(); + if (PowerArchitecturePPC64 >= 9) { +#if !defined(VM_LITTLE_ENDIAN) + stxv(vsr, offs, base); // all vector load/store instructions use the same byte order on BE +#else + if (offs == 0) { + stxvb16x(vsr, base); + } else { + li(tmp, offs); + stxvb16x(vsr, base, tmp); + } +#endif + } else { // Power8 only supports very limited instructions +#if defined(VM_LITTLE_ENDIAN) + // need to swap bytes in both double-words + if (vtmp != vnoreg) { + vperm(vtmp, val, val, vp); + vsr = vtmp->to_vsr(); + } else { + vperm(val, val, val, vp); // clobbers val! + } +#endif + if (offs == 0) { + stxvd2x(vsr, base); + } else { + li(tmp, offs); + stxvd2x(vsr, base, tmp); + } + } +} + +inline void Assembler::compute_vp_for_byte_vector_unaligned(VectorRegister dest, VectorRegister vtmp) { +#if defined(VM_LITTLE_ENDIAN) + if (PowerArchitecturePPC64 < 9) { + li(R0, 0); + vspltisb(vtmp, 7); // vtmp = [7, ..., 7] + lvsl(dest, R0); // dest = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + vxor(dest, dest, vtmp); // dest = [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8] + } +#endif +} + +inline void Assembler::load_word_vector_unaligned(VectorRegister dest, int offs, Register base, Register tmp) { + VectorSRegister vsr = dest->to_vsr(); +#if !defined(VM_LITTLE_ENDIAN) + if (PowerArchitecturePPC64 >= 9) { + lxv(vsr, offs, base); // all vector load/store instructions use the same byte order on BE + } else +#endif + if (offs == 0) { + lxvw4x(vsr, base); + } else { + li(tmp, offs); + lxvw4x(vsr, base, tmp); + } +} + +inline void Assembler::store_word_vector_unaligned(VectorRegister val, int offs, Register base, Register tmp) { + VectorSRegister vsr = val->to_vsr(); +#if !defined(VM_LITTLE_ENDIAN) + if (PowerArchitecturePPC64 >= 9) { + stxv(vsr, offs, base); // all vector load/store instructions use the same byte order on BE + } else +#endif + if (offs == 0) { + stxvw4x(vsr, base); + } else { + li(tmp, offs); + stxvw4x(vsr, base, tmp); + } +} + inline void Assembler::load_const(Register d, void* x, Register tmp) { load_const(d, (long)x, tmp); } diff --git a/src/hotspot/cpu/ppc/bytes_ppc.hpp b/src/hotspot/cpu/ppc/bytes_ppc.hpp deleted file mode 100644 index d6076a9c5b2e..000000000000 --- a/src/hotspot/cpu/ppc/bytes_ppc.hpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2022 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_PPC_BYTES_PPC_HPP -#define CPU_PPC_BYTES_PPC_HPP - -#include "memory/allStatic.hpp" -#include "utilities/byteswap.hpp" - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - // PowerPC needs to check for alignment. - - // Can I count on address always being a pointer to an unsigned char? Yes. - -#if defined(VM_LITTLE_ENDIAN) - - static inline u2 get_native_u2(address p) { - return (intptr_t(p) & 1) == 0 - ? *(u2*)p - : ( u2(p[1]) << 8 ) - | ( u2(p[0]) ); - } - - static inline u4 get_native_u4(address p) { - switch (intptr_t(p) & 3) { - case 0: return *(u4*)p; - - case 2: return ( u4( ((u2*)p)[1] ) << 16 ) - | ( u4( ((u2*)p)[0] ) ); - - default: return ( u4(p[3]) << 24 ) - | ( u4(p[2]) << 16 ) - | ( u4(p[1]) << 8 ) - | u4(p[0]); - } - } - - static inline u8 get_native_u8(address p) { - switch (intptr_t(p) & 7) { - case 0: return *(u8*)p; - - case 4: return ( u8( ((u4*)p)[1] ) << 32 ) - | ( u8( ((u4*)p)[0] ) ); - - case 2: return ( u8( ((u2*)p)[3] ) << 48 ) - | ( u8( ((u2*)p)[2] ) << 32 ) - | ( u8( ((u2*)p)[1] ) << 16 ) - | ( u8( ((u2*)p)[0] ) ); - - default: return ( u8(p[7]) << 56 ) - | ( u8(p[6]) << 48 ) - | ( u8(p[5]) << 40 ) - | ( u8(p[4]) << 32 ) - | ( u8(p[3]) << 24 ) - | ( u8(p[2]) << 16 ) - | ( u8(p[1]) << 8 ) - | u8(p[0]); - } - } - - - - static inline void put_native_u2(address p, u2 x) { - if ( (intptr_t(p) & 1) == 0 ) *(u2*)p = x; - else { - p[1] = x >> 8; - p[0] = x; - } - } - - static inline void put_native_u4(address p, u4 x) { - switch ( intptr_t(p) & 3 ) { - case 0: *(u4*)p = x; - break; - - case 2: ((u2*)p)[1] = x >> 16; - ((u2*)p)[0] = x; - break; - - default: ((u1*)p)[3] = x >> 24; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[0] = x; - break; - } - } - - static inline void put_native_u8(address p, u8 x) { - switch ( intptr_t(p) & 7 ) { - case 0: *(u8*)p = x; - break; - - case 4: ((u4*)p)[1] = x >> 32; - ((u4*)p)[0] = x; - break; - - case 2: ((u2*)p)[3] = x >> 48; - ((u2*)p)[2] = x >> 32; - ((u2*)p)[1] = x >> 16; - ((u2*)p)[0] = x; - break; - - default: ((u1*)p)[7] = x >> 56; - ((u1*)p)[6] = x >> 48; - ((u1*)p)[5] = x >> 40; - ((u1*)p)[4] = x >> 32; - ((u1*)p)[3] = x >> 24; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[0] = x; - } - } - - // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) - // (no byte-order reversal is needed since Power CPUs are big-endian oriented). - static inline u2 get_Java_u2(address p) { return byteswap(get_native_u2(p)); } - static inline u4 get_Java_u4(address p) { return byteswap(get_native_u4(p)); } - static inline u8 get_Java_u8(address p) { return byteswap(get_native_u8(p)); } - - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, byteswap(x)); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, byteswap(x)); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, byteswap(x)); } - -#else // !defined(VM_LITTLE_ENDIAN) - - static inline u2 get_native_u2(address p) { - return (intptr_t(p) & 1) == 0 - ? *(u2*)p - : ( u2(p[0]) << 8 ) - | ( u2(p[1]) ); - } - - static inline u4 get_native_u4(address p) { - switch (intptr_t(p) & 3) { - case 0: return *(u4*)p; - - case 2: return ( u4( ((u2*)p)[0] ) << 16 ) - | ( u4( ((u2*)p)[1] ) ); - - default: return ( u4(p[0]) << 24 ) - | ( u4(p[1]) << 16 ) - | ( u4(p[2]) << 8 ) - | u4(p[3]); - } - } - - static inline u8 get_native_u8(address p) { - switch (intptr_t(p) & 7) { - case 0: return *(u8*)p; - - case 4: return ( u8( ((u4*)p)[0] ) << 32 ) - | ( u8( ((u4*)p)[1] ) ); - - case 2: return ( u8( ((u2*)p)[0] ) << 48 ) - | ( u8( ((u2*)p)[1] ) << 32 ) - | ( u8( ((u2*)p)[2] ) << 16 ) - | ( u8( ((u2*)p)[3] ) ); - - default: return ( u8(p[0]) << 56 ) - | ( u8(p[1]) << 48 ) - | ( u8(p[2]) << 40 ) - | ( u8(p[3]) << 32 ) - | ( u8(p[4]) << 24 ) - | ( u8(p[5]) << 16 ) - | ( u8(p[6]) << 8 ) - | u8(p[7]); - } - } - - - - static inline void put_native_u2(address p, u2 x) { - if ( (intptr_t(p) & 1) == 0 ) { *(u2*)p = x; } - else { - p[0] = x >> 8; - p[1] = x; - } - } - - static inline void put_native_u4(address p, u4 x) { - switch ( intptr_t(p) & 3 ) { - case 0: *(u4*)p = x; - break; - - case 2: ((u2*)p)[0] = x >> 16; - ((u2*)p)[1] = x; - break; - - default: ((u1*)p)[0] = x >> 24; - ((u1*)p)[1] = x >> 16; - ((u1*)p)[2] = x >> 8; - ((u1*)p)[3] = x; - break; - } - } - - static inline void put_native_u8(address p, u8 x) { - switch ( intptr_t(p) & 7 ) { - case 0: *(u8*)p = x; - break; - - case 4: ((u4*)p)[0] = x >> 32; - ((u4*)p)[1] = x; - break; - - case 2: ((u2*)p)[0] = x >> 48; - ((u2*)p)[1] = x >> 32; - ((u2*)p)[2] = x >> 16; - ((u2*)p)[3] = x; - break; - - default: ((u1*)p)[0] = x >> 56; - ((u1*)p)[1] = x >> 48; - ((u1*)p)[2] = x >> 40; - ((u1*)p)[3] = x >> 32; - ((u1*)p)[4] = x >> 24; - ((u1*)p)[5] = x >> 16; - ((u1*)p)[6] = x >> 8; - ((u1*)p)[7] = x; - } - } - - // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) - // (no byte-order reversal is needed since Power CPUs are big-endian oriented). - static inline u2 get_Java_u2(address p) { return get_native_u2(p); } - static inline u4 get_Java_u4(address p) { return get_native_u4(p); } - static inline u8 get_Java_u8(address p) { return get_native_u8(p); } - - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, x); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, x); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, x); } - -#endif // VM_LITTLE_ENDIAN -}; - -#endif // CPU_PPC_BYTES_PPC_HPP diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp index f86b0a9d4fc9..74a8e17dd700 100644 --- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp @@ -155,6 +155,7 @@ LoadFlattenedArrayStub::LoadFlattenedArrayStub(LIR_Opr array, LIR_Opr index, LIR void LoadFlattenedArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); + __ extsw(_index->as_register(), _index->as_register()); // see CCallingConventionRequiresIntsAsLongs // Pass arguments on stack. __ std(_array->as_register(), -16, R1_SP); __ std(_index->as_register(), -8, R1_SP); @@ -182,6 +183,7 @@ StoreFlattenedArrayStub::StoreFlattenedArrayStub(LIR_Opr array, LIR_Opr index, L void StoreFlattenedArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); + __ extsw(_index->as_register(), _index->as_register()); // see CCallingConventionRequiresIntsAsLongs // Pass arguments on stack. __ std(_array->as_register(), -24, R1_SP); __ std(_index->as_register(), -16, R1_SP); diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index d6051da562a3..cd9bb80d9507 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -3127,13 +3127,8 @@ void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // We are storing into an array that *may* be null-free (the declared type is // Object[], abstract[], interface[] or VT.ref[]). - Label test_mark_word; Register tmp = op->tmp()->as_register(); __ ld(tmp, oopDesc::mark_offset_in_bytes(), op->array()->as_register()); - __ andi_(R0, tmp, markWord::unlocked_value); - __ bne(CR0, test_mark_word); - __ load_prototype_header(tmp, op->array()->as_register()); - __ bind(test_mark_word); __ andi(R0, tmp, markWord::null_free_array_bit_in_place); __ cmpwi(BOOL_RESULT, R0, 0); } diff --git a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp index d550c33b1122..909d1e585825 100644 --- a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025 SAP SE. All rights reserved. + * Copyright (c) 2020, 2026 SAP SE. All rights reserved. * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -297,7 +297,7 @@ void DowncallLinker::StubGenerator::generate() { Label L_after_reguard; if (_needs_transition) { - __ li(tmp, _thread_in_vm); + __ li(tmp, _thread_in_Java); __ release(); __ stw(tmp, in_bytes(JavaThread::thread_state_offset()), R16_thread); if (!UseSystemMemoryBarrier) { @@ -311,11 +311,6 @@ void DowncallLinker::StubGenerator::generate() { __ bne(CR0, L_safepoint_poll_slow_path); __ bind(L_after_safepoint_poll); - // change thread state - __ li(tmp, _thread_in_Java); - __ lwsync(); // Acquire safepoint and suspend state, release thread state. - __ stw(tmp, in_bytes(JavaThread::thread_state_offset()), R16_thread); - __ block_comment("reguard stack check"); __ lwz(tmp, in_bytes(JavaThread::stack_guard_state_offset()), R16_thread); __ cmpwi(CR0, tmp, StackOverflow::stack_guard_yellow_reserved_disabled); @@ -340,7 +335,7 @@ void DowncallLinker::StubGenerator::generate() { out_reg_spiller.generate_spill(_masm, out_spill_offset); } - __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, JavaThread::check_special_condition_for_native_trans), R0); + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, SharedRuntime::check_special_condition_for_native_trans), R0); __ mr(R3_ARG1, R16_thread); __ call_c(call_target_address); @@ -374,5 +369,5 @@ void DowncallLinker::StubGenerator::generate() { ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. } diff --git a/src/hotspot/cpu/ppc/interpreterRT_ppc.cpp b/src/hotspot/cpu/ppc/interpreterRT_ppc.cpp index dd2503bd54b8..233713b0ecd8 100644 --- a/src/hotspot/cpu/ppc/interpreterRT_ppc.cpp +++ b/src/hotspot/cpu/ppc/interpreterRT_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin __ load_const(R3_RET, AbstractInterpreter::result_handler(method()->result_type())); __ blr(); - __ flush(); + __ invalidate_icache(); } #undef __ diff --git a/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp b/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp index ac3d2d5dba85..033a25b62f2d 100644 --- a/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp +++ b/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp @@ -154,7 +154,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { __ load_const_optimized(R12, slow_case_addr, R0); __ call_c_and_return_to_caller(R12); // tail call - __ flush(); + __ invalidate_icache(); return fast_entry; } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index e7bf14dad340..c48071291062 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2734,7 +2734,7 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Check for monitor (0b10) or locked (0b00). ld(mark, oopDesc::mark_offset_in_bytes(), obj); andi_(R0, mark, markWord::lock_mask_in_place); - cmpldi(CR0, R0, markWord::unlocked_value); + cmpldi(CR0, R0, markWord::lock_neutral_value); bgt(CR0, inflated); bne(CR0, slow_path); @@ -2913,7 +2913,7 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe #ifdef ASSERT // Check header not unlocked (0b01). Label not_unlocked; - andi_(t, mark, markWord::unlocked_value); + andi_(t, mark, markWord::lock_neutral_value); beq(CR0, not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); @@ -3374,11 +3374,6 @@ void MacroAssembler::load_metadata(Register dst, Register src) { } } -void MacroAssembler::load_prototype_header(Register dst, Register src) { - load_klass(dst, src); - ld(dst, Klass::prototype_header_offset(), dst); -} - void MacroAssembler::flat_field_copy(DecoratorSet decorators, Register src, Register dst, Register inline_layout_info) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bs->flat_field_copy(this, decorators, src, dst, inline_layout_info); @@ -4838,17 +4833,18 @@ void MacroAssembler::atomically_flip_locked_state(bool is_unlock, Register obj, } bind(retry); - STATIC_ASSERT(markWord::locked_value == 0); // Or need to change this! + STATIC_ASSERT(markWord::fast_locked_value == 0); // Or need to change this! + STATIC_ASSERT(markWord::lock_neutral_value == 1); // Or need to change this! if (!is_unlock) { ldarx(tmp, obj, MacroAssembler::cmpxchgx_hint_acquire_lock()); - xori(tmp, tmp, markWord::unlocked_value); // flip unlocked bit + xori(tmp, tmp, markWord::lock_neutral_value); // flip lock-neutral bit andi_(R0, tmp, markWord::lock_mask_in_place | markWord::inline_type_bit_in_place); - bne(CR0, failed); // failed if new header doesn't contain locked_value (which is 0) or belongs to an inline type + bne(CR0, failed); // failed if new header doesn't contain fast_locked_value (which is 0) or belongs to an inline type } else { ldarx(tmp, obj, MacroAssembler::cmpxchgx_hint_release_lock()); andi_(R0, tmp, markWord::lock_mask_in_place); - bne(CR0, failed); // failed if old header doesn't contain locked_value (which is 0) - ori(tmp, tmp, markWord::unlocked_value); // set unlocked bit + bne(CR0, failed); // failed if old header doesn't contain fast_locked_value (which is 0) + ori(tmp, tmp, markWord::lock_neutral_value); // set lock-neutral bit } stdcx_(tmp, obj); bne(CR0, retry); @@ -4900,7 +4896,7 @@ void MacroAssembler::fast_lock(Register box, Register obj, Register t1, Register // Check header for monitor (0b10) or locked (0b00). ld(mark, oopDesc::mark_offset_in_bytes(), obj); - xori(t, mark, markWord::unlocked_value); + xori(t, mark, markWord::lock_neutral_value); andi_(t, t, markWord::lock_mask_in_place); bne(CR0, slow); @@ -4974,7 +4970,7 @@ void MacroAssembler::fast_unlock(Register obj, Register t1, Label& slow) { #ifdef ASSERT // Check header not unlocked (0b01). Label not_unlocked; - andi_(t, mark, markWord::unlocked_value); + andi_(t, mark, markWord::lock_neutral_value); beq(CR0, not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp index 533d03230a4d..839e5dcd69d9 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp @@ -846,8 +846,6 @@ class MacroAssembler: public Assembler { void flat_field_copy(DecoratorSet decorators, Register src, Register dst, Register inline_layout_info); - void load_prototype_header(Register dst, Register src); - void inline_layout_info(Register holder_klass, Register index, Register layout_info); // inline type data payload offsets... diff --git a/src/hotspot/cpu/ppc/runtime_ppc.cpp b/src/hotspot/cpu/ppc/runtime_ppc.cpp index ab658e9de58b..a1ba80cad5b7 100644 --- a/src/hotspot/cpu/ppc/runtime_ppc.cpp +++ b/src/hotspot/cpu/ppc/runtime_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,8 +141,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ mtlr(R4_ARG2); __ bctr(); - // Make sure all code is generated. - masm->flush(); + // Code will be copied. No ICache sync required. // Set exception blob. return ExceptionBlob::create(&buffer, oop_maps, diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 553934953873..ae86f80cff4c 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -2169,7 +2169,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, assert(vep_offset != -1, "Must be set"); #endif - __ flush(); + // Code will be copied. No ICache sync required. nmethod* nm = nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -2198,7 +2198,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, in_sig_bt, in_regs); int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period - __ flush(); + // Code will be copied. No ICache sync required. int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually return nmethod::new_native_nmethod(method, compile_id, @@ -2617,8 +2617,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, } // Publish thread state - // Transition from _thread_in_native to _thread_in_vm. - __ li(R0, _thread_in_vm); + // Transition from _thread_in_native. + __ li(R0, _thread_in_Java); __ release(); // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); __ stw(R0, thread_(thread_state)); @@ -2642,7 +2642,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, Register suspend_flags = r_temp_6; // No synchronization in progress nor yet synchronized - // (cmp-br-isync on one path, release (same as acquire on PPC64) on the other path). __ safepoint_poll(sync, sync_state, true /* at_return */, false /* in_nmethod */); // Not suspended. @@ -2656,28 +2655,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // lets us share the oopMap we used when we went native rather than create // a distinct one for this pc. __ bind(sync); - __ isync(); address entry_point = - CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans); + CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans); save_native_result(masm, ret_type, workspace_slot_offset); __ call_VM_leaf(entry_point, R16_thread); restore_native_result(masm, ret_type, workspace_slot_offset); __ bind(no_block); - // Publish thread state. - // -------------------------------------------------------------------------- - - // Thread state is _thread_in_vm. Any safepoint blocking has - // already happened so we can now change state to _thread_in_Java. - - // Transition from _thread_in_vm to _thread_in_Java. - __ li(R0, _thread_in_Java); - __ lwsync(); // Acquire safepoint and suspend state, release thread state. - // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); - __ stw(R0, thread_(thread_state)); - // Check preemption for Object.wait() if (method->is_object_wait0()) { Label not_preempted; @@ -2836,7 +2822,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Done. // -------------------------------------------------------------------------- - __ flush(); + // Code will be copied. No ICache sync required. nmethod *nm = nmethod::new_native_nmethod(method, compile_id, @@ -3203,8 +3189,7 @@ void SharedRuntime::generate_deopt_blob() { __ unimplemented("deopt blob needed only with compiler"); #endif - // Make sure all code is generated - __ flush(); + // Code will be copied. No ICache sync required. _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, first_frame_size_in_bytes / wordSize); @@ -3341,7 +3326,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Return to the interpreter entry point. __ blr(); - masm->flush(); + // Code will be copied. No ICache sync required. return UncommonTrapBlob::create(&buffer, oop_maps, frame_size_in_bytes/wordSize); } @@ -3447,8 +3432,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ blr(); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Fill-out other meta info // CodeBlob frame size is in words. @@ -3534,9 +3518,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ std(R11_scratch1, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); __ b64_patchable(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); - // ------------- - // Make sure all code is generated. - masm->flush(); + // Code will be copied. No ICache sync required. // return the blob // frame_size_words or bytes?? diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index c1a6b54df0bf..2d51119bcc9f 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -580,7 +580,8 @@ class StubGenerator: public StubCodeGenerator { // // address generate_ghash_processBlocks() { - StubCodeMark mark(this, "StubRoutines", "ghash"); + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; + StubCodeMark mark(this, stub_id); address start = __ function_entry(); // Registers for parameters @@ -2781,10 +2782,8 @@ class StubGenerator: public StubCodeGenerator { Register to = R4_ARG2; // destination array address Register key = R5_ARG3; // round key array - Register keylen = R8; - Register temp = R9; - Register keypos = R10; - Register fifteen = R12; + Register keylen = R6; + Register tmp = R7; VectorRegister vRet = VR0; @@ -2793,68 +2792,27 @@ class StubGenerator: public StubCodeGenerator { VectorRegister vKey3 = VR3; VectorRegister vKey4 = VR4; - VectorRegister fromPerm = VR5; - VectorRegister keyPerm = VR6; - VectorRegister toPerm = VR7; - VectorRegister fSplt = VR8; - - VectorRegister vTmp1 = VR9; - VectorRegister vTmp2 = VR10; - VectorRegister vTmp3 = VR11; - VectorRegister vTmp4 = VR12; + VectorRegister vp = VR6; // permute vector for byte vector accesses on P8 LE - __ li (fifteen, 15); + __ compute_vp_for_byte_vector_unaligned(vp, /*temp*/ vRet); // load unaligned from[0-15] to vRet - __ lvx (vRet, from); - __ lvx (vTmp1, fifteen, from); - __ lvsl (fromPerm, from); -#ifdef VM_LITTLE_ENDIAN - __ vspltisb (fSplt, 0x0f); - __ vxor (fromPerm, fromPerm, fSplt); -#endif - __ vperm (vRet, vRet, vTmp1, fromPerm); + __ load_byte_vector_unaligned(vRet, 0, from, tmp, vp); + + // load the 1st round key to vKey1 + __ load_word_vector_unaligned(vKey1, 0, key, tmp); // load keylen (44 or 52 or 60) __ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT), key); - // to load keys - __ load_perm (keyPerm, key); -#ifdef VM_LITTLE_ENDIAN - __ vspltisb (vTmp2, -16); - __ vrld (keyPerm, keyPerm, vTmp2); - __ vrld (keyPerm, keyPerm, vTmp2); - __ vsldoi (keyPerm, keyPerm, keyPerm, 8); -#endif - - // load the 1st round key to vTmp1 - __ lvx (vTmp1, key); - __ li (keypos, 16); - __ lvx (vKey1, keypos, key); - __ vec_perm (vTmp1, vKey1, keyPerm); - // 1st round - __ vxor (vRet, vRet, vTmp1); - - // load the 2nd round key to vKey1 - __ li (keypos, 32); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vKey2, keyPerm); - - // load the 3rd round key to vKey2 - __ li (keypos, 48); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, keyPerm); - - // load the 4th round key to vKey3 - __ li (keypos, 64); - __ lvx (vKey4, keypos, key); - __ vec_perm (vKey3, vKey4, keyPerm); + __ vxor (vRet, vRet, vKey1); - // load the 5th round key to vKey4 - __ li (keypos, 80); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey4, vTmp1, keyPerm); + // load the 2nd - 5th round key to vKey1 - vKey4 + __ load_word_vector_unaligned(vKey1, 16, key, tmp); + __ load_word_vector_unaligned(vKey2, 32, key, tmp); + __ load_word_vector_unaligned(vKey3, 48, key, tmp); + __ load_word_vector_unaligned(vKey4, 64, key, tmp); // 2nd - 5th rounds __ vcipher (vRet, vRet, vKey1); @@ -2862,25 +2820,11 @@ class StubGenerator: public StubCodeGenerator { __ vcipher (vRet, vRet, vKey3); __ vcipher (vRet, vRet, vKey4); - // load the 6th round key to vKey1 - __ li (keypos, 96); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vTmp1, vKey2, keyPerm); - - // load the 7th round key to vKey2 - __ li (keypos, 112); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, keyPerm); - - // load the 8th round key to vKey3 - __ li (keypos, 128); - __ lvx (vKey4, keypos, key); - __ vec_perm (vKey3, vKey4, keyPerm); - - // load the 9th round key to vKey4 - __ li (keypos, 144); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey4, vTmp1, keyPerm); + // load the 6th - 9th round key to vKey1 - vKey4 + __ load_word_vector_unaligned(vKey1, 80, key, tmp); + __ load_word_vector_unaligned(vKey2, 96, key, tmp); + __ load_word_vector_unaligned(vKey3, 112, key, tmp); + __ load_word_vector_unaligned(vKey4, 128, key, tmp); // 6th - 9th rounds __ vcipher (vRet, vRet, vKey1); @@ -2888,15 +2832,9 @@ class StubGenerator: public StubCodeGenerator { __ vcipher (vRet, vRet, vKey3); __ vcipher (vRet, vRet, vKey4); - // load the 10th round key to vKey1 - __ li (keypos, 160); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vTmp1, vKey2, keyPerm); - - // load the 11th round key to vKey2 - __ li (keypos, 176); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey2, vTmp1, keyPerm); + // load the 10th - 11th round key to vKey1 - vKey2 + __ load_word_vector_unaligned(vKey1, 144, key, tmp); + __ load_word_vector_unaligned(vKey2, 160, key, tmp); // if all round keys are loaded, skip next 4 rounds __ cmpwi (CR0, keylen, 44); @@ -2906,15 +2844,9 @@ class StubGenerator: public StubCodeGenerator { __ vcipher (vRet, vRet, vKey1); __ vcipher (vRet, vRet, vKey2); - // load the 12th round key to vKey1 - __ li (keypos, 192); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vTmp1, vKey2, keyPerm); - - // load the 13th round key to vKey2 - __ li (keypos, 208); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey2, vTmp1, keyPerm); + // load the 12th - 13th round key to vKey1 - vKey2 + __ load_word_vector_unaligned(vKey1, 176, key, tmp); + __ load_word_vector_unaligned(vKey2, 192, key, tmp); // if all round keys are loaded, skip next 2 rounds __ cmpwi (CR0, keylen, 52); @@ -2929,15 +2861,9 @@ class StubGenerator: public StubCodeGenerator { __ vcipher (vRet, vRet, vKey1); __ vcipher (vRet, vRet, vKey2); - // load the 14th round key to vKey1 - __ li (keypos, 224); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vTmp1, vKey2, keyPerm); - - // load the 15th round key to vKey2 - __ li (keypos, 240); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey2, vTmp1, keyPerm); + // load the 14th - 15th round key to vKey1 - vKey2 + __ load_word_vector_unaligned(vKey1, 208, key, tmp); + __ load_word_vector_unaligned(vKey2, 224, key, tmp); __ bind(L_doLast); @@ -2945,23 +2871,8 @@ class StubGenerator: public StubCodeGenerator { __ vcipher (vRet, vRet, vKey1); __ vcipherlast (vRet, vRet, vKey2); -#ifdef VM_LITTLE_ENDIAN - // toPerm = 0x0F0E0D0C0B0A09080706050403020100 - __ lvsl (toPerm, keypos); // keypos is a multiple of 16 - __ vxor (toPerm, toPerm, fSplt); - - // Swap Bytes - __ vperm (vRet, vRet, vRet, toPerm); -#endif - // store result (unaligned) - // Note: We can't use a read-modify-write sequence which touches additional Bytes. - Register lo = temp, hi = fifteen; // Reuse - __ vsldoi (vTmp1, vRet, vRet, 8); - __ mfvrd (hi, vRet); - __ mfvrd (lo, vTmp1); - __ std (hi, 0 LITTLE_ENDIAN_ONLY(+ 8), to); - __ std (lo, 0 BIG_ENDIAN_ONLY(+ 8), to); + __ store_byte_vector_unaligned(vRet, 0, to, tmp, vp); __ blr(); @@ -2989,10 +2900,8 @@ class StubGenerator: public StubCodeGenerator { Register to = R4_ARG2; // destination array address Register key = R5_ARG3; // round key array - Register keylen = R8; - Register temp = R9; - Register keypos = R10; - Register fifteen = R12; + Register keylen = R6; + Register tmp = R7; VectorRegister vRet = VR0; @@ -3002,41 +2911,16 @@ class StubGenerator: public StubCodeGenerator { VectorRegister vKey4 = VR4; VectorRegister vKey5 = VR5; - VectorRegister fromPerm = VR6; - VectorRegister keyPerm = VR7; - VectorRegister toPerm = VR8; - VectorRegister fSplt = VR9; - - VectorRegister vTmp1 = VR10; - VectorRegister vTmp2 = VR11; - VectorRegister vTmp3 = VR12; - VectorRegister vTmp4 = VR13; + VectorRegister vp = VR6; // permute vector for byte vector accesses on P8 LE - __ li (fifteen, 15); + __ compute_vp_for_byte_vector_unaligned(vp, /*temp*/ vRet); // load unaligned from[0-15] to vRet - __ lvx (vRet, from); - __ lvx (vTmp1, fifteen, from); - __ lvsl (fromPerm, from); -#ifdef VM_LITTLE_ENDIAN - __ vspltisb (fSplt, 0x0f); - __ vxor (fromPerm, fromPerm, fSplt); -#endif - __ vperm (vRet, vRet, vTmp1, fromPerm); // align [and byte swap in LE] + __ load_byte_vector_unaligned(vRet, 0, from, tmp, vp); // load keylen (44 or 52 or 60) __ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT), key); - // to load keys - __ load_perm (keyPerm, key); -#ifdef VM_LITTLE_ENDIAN - __ vxor (vTmp2, vTmp2, vTmp2); - __ vspltisb (vTmp2, -16); - __ vrld (keyPerm, keyPerm, vTmp2); - __ vrld (keyPerm, keyPerm, vTmp2); - __ vsldoi (keyPerm, keyPerm, keyPerm, 8); -#endif - __ cmpwi (CR0, keylen, 44); __ beq (CR0, L_do44); @@ -3048,32 +2932,12 @@ class StubGenerator: public StubCodeGenerator { __ bne (CR0, L_error); #endif - // load the 15th round key to vKey1 - __ li (keypos, 240); - __ lvx (vKey1, keypos, key); - __ li (keypos, 224); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vKey2, vKey1, keyPerm); - - // load the 14th round key to vKey2 - __ li (keypos, 208); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, vKey2, keyPerm); - - // load the 13th round key to vKey3 - __ li (keypos, 192); - __ lvx (vKey4, keypos, key); - __ vec_perm (vKey3, vKey4, vKey3, keyPerm); - - // load the 12th round key to vKey4 - __ li (keypos, 176); - __ lvx (vKey5, keypos, key); - __ vec_perm (vKey4, vKey5, vKey4, keyPerm); - - // load the 11th round key to vKey5 - __ li (keypos, 160); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey5, vTmp1, vKey5, keyPerm); + // load the 15th - 11th round key to vKey1 - vKey5 + __ load_word_vector_unaligned(vKey1, 224, key, tmp); + __ load_word_vector_unaligned(vKey2, 208, key, tmp); + __ load_word_vector_unaligned(vKey3, 192, key, tmp); + __ load_word_vector_unaligned(vKey4, 176, key, tmp); + __ load_word_vector_unaligned(vKey5, 160, key, tmp); // 1st - 5th rounds __ vxor (vRet, vRet, vKey1); @@ -3087,22 +2951,10 @@ class StubGenerator: public StubCodeGenerator { __ align(32); __ bind (L_do52); - // load the 13th round key to vKey1 - __ li (keypos, 208); - __ lvx (vKey1, keypos, key); - __ li (keypos, 192); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vKey2, vKey1, keyPerm); - - // load the 12th round key to vKey2 - __ li (keypos, 176); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, vKey2, keyPerm); - - // load the 11th round key to vKey3 - __ li (keypos, 160); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey3, vTmp1, vKey3, keyPerm); + // load the 13th - 11th round key to vKey1 - vKey3 + __ load_word_vector_unaligned(vKey1, 192, key, tmp); + __ load_word_vector_unaligned(vKey2, 176, key, tmp); + __ load_word_vector_unaligned(vKey3, 160, key, tmp); // 1st - 3rd rounds __ vxor (vRet, vRet, vKey1); @@ -3115,41 +2967,19 @@ class StubGenerator: public StubCodeGenerator { __ bind (L_do44); // load the 11th round key to vKey1 - __ li (keypos, 176); - __ lvx (vKey1, keypos, key); - __ li (keypos, 160); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey1, vTmp1, vKey1, keyPerm); + __ load_word_vector_unaligned(vKey1, 160, key, tmp); // 1st round __ vxor (vRet, vRet, vKey1); __ bind (L_doLast); - // load the 10th round key to vKey1 - __ li (keypos, 144); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vKey2, vTmp1, keyPerm); - - // load the 9th round key to vKey2 - __ li (keypos, 128); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, vKey2, keyPerm); - - // load the 8th round key to vKey3 - __ li (keypos, 112); - __ lvx (vKey4, keypos, key); - __ vec_perm (vKey3, vKey4, vKey3, keyPerm); - - // load the 7th round key to vKey4 - __ li (keypos, 96); - __ lvx (vKey5, keypos, key); - __ vec_perm (vKey4, vKey5, vKey4, keyPerm); - - // load the 6th round key to vKey5 - __ li (keypos, 80); - __ lvx (vTmp1, keypos, key); - __ vec_perm (vKey5, vTmp1, vKey5, keyPerm); + // load the 10th - 6th round key to vKey1 - vKey5 + __ load_word_vector_unaligned(vKey1, 144, key, tmp); + __ load_word_vector_unaligned(vKey2, 128, key, tmp); + __ load_word_vector_unaligned(vKey3, 112, key, tmp); + __ load_word_vector_unaligned(vKey4, 96, key, tmp); + __ load_word_vector_unaligned(vKey5, 80, key, tmp); // last 10th - 6th rounds __ vncipher (vRet, vRet, vKey1); @@ -3158,29 +2988,12 @@ class StubGenerator: public StubCodeGenerator { __ vncipher (vRet, vRet, vKey4); __ vncipher (vRet, vRet, vKey5); - // load the 5th round key to vKey1 - __ li (keypos, 64); - __ lvx (vKey2, keypos, key); - __ vec_perm (vKey1, vKey2, vTmp1, keyPerm); - - // load the 4th round key to vKey2 - __ li (keypos, 48); - __ lvx (vKey3, keypos, key); - __ vec_perm (vKey2, vKey3, vKey2, keyPerm); - - // load the 3rd round key to vKey3 - __ li (keypos, 32); - __ lvx (vKey4, keypos, key); - __ vec_perm (vKey3, vKey4, vKey3, keyPerm); - - // load the 2nd round key to vKey4 - __ li (keypos, 16); - __ lvx (vKey5, keypos, key); - __ vec_perm (vKey4, vKey5, vKey4, keyPerm); - - // load the 1st round key to vKey5 - __ lvx (vTmp1, key); - __ vec_perm (vKey5, vTmp1, vKey5, keyPerm); + // load the 5th - 1st round key to vKey1 - vKey5 + __ load_word_vector_unaligned(vKey1, 64, key, tmp); + __ load_word_vector_unaligned(vKey2, 48, key, tmp); + __ load_word_vector_unaligned(vKey3, 32, key, tmp); + __ load_word_vector_unaligned(vKey4, 16, key, tmp); + __ load_word_vector_unaligned(vKey5, 0, key, tmp); // last 5th - 1th rounds __ vncipher (vRet, vRet, vKey1); @@ -3189,23 +3002,8 @@ class StubGenerator: public StubCodeGenerator { __ vncipher (vRet, vRet, vKey4); __ vncipherlast (vRet, vRet, vKey5); -#ifdef VM_LITTLE_ENDIAN - // toPerm = 0x0F0E0D0C0B0A09080706050403020100 - __ lvsl (toPerm, keypos); // keypos is a multiple of 16 - __ vxor (toPerm, toPerm, fSplt); - - // Swap Bytes - __ vperm (vRet, vRet, vRet, toPerm); -#endif - // store result (unaligned) - // Note: We can't use a read-modify-write sequence which touches additional Bytes. - Register lo = temp, hi = fifteen; // Reuse - __ vsldoi (vTmp1, vRet, vRet, 8); - __ mfvrd (hi, vRet); - __ mfvrd (lo, vTmp1); - __ std (hi, 0 LITTLE_ENDIAN_ONLY(+ 8), to); - __ std (lo, 0 BIG_ENDIAN_ONLY(+ 8), to); + __ store_byte_vector_unaligned(vRet, 0, to, tmp, vp); __ blr(); @@ -3216,6 +3014,306 @@ class StubGenerator: public StubCodeGenerator { return start; } + // ========================================================================== + // AES helper functions for PPC64 + // + // These emit the AES round instructions. + // Each call to these helpers emits a sequence of vcipher/vncipher + // instructions. + // + // ========================================================================== + // Emits the AES encrypt round instructions. + // + // vRet: in/out — the AES state (plaintext in, ciphertext out) + // key: register holding pointer to expanded key array + // keylen: register holding key length (44/52/60) + // + void aes_encrypt_rounds(VectorRegister vRet, + Register key, Register keylen, Register tmp, + VectorRegister vKey1, VectorRegister vKey2, + VectorRegister vKey3, VectorRegister vKey4) { + Label L_doLast; + + // round 0: AddRoundKey + __ load_word_vector_unaligned(vKey1, 0, key, tmp); + __ vxor (vRet, vRet, vKey1); + + // rounds 2-5 + __ load_word_vector_unaligned(vKey1, 16, key, tmp); + __ load_word_vector_unaligned(vKey2, 32, key, tmp); + __ load_word_vector_unaligned(vKey3, 48, key, tmp); + __ load_word_vector_unaligned(vKey4, 64, key, tmp); + __ vcipher (vRet, vRet, vKey1); + __ vcipher (vRet, vRet, vKey2); + __ vcipher (vRet, vRet, vKey3); + __ vcipher (vRet, vRet, vKey4); + + // rounds 6-9 + __ load_word_vector_unaligned(vKey1, 80, key, tmp); + __ load_word_vector_unaligned(vKey2, 96, key, tmp); + __ load_word_vector_unaligned(vKey3, 112, key, tmp); + __ load_word_vector_unaligned(vKey4, 128, key, tmp); + __ vcipher (vRet, vRet, vKey1); + __ vcipher (vRet, vRet, vKey2); + __ vcipher (vRet, vRet, vKey3); + __ vcipher (vRet, vRet, vKey4); + + // rounds 10-11 + __ load_word_vector_unaligned(vKey1, 144, key, tmp); + __ load_word_vector_unaligned(vKey2, 160, key, tmp); + + __ cmpwi (CR0, keylen, 44); // AES-128 -> final rounds + __ beq (CR0, L_doLast); + + __ vcipher (vRet, vRet, vKey1); + __ vcipher (vRet, vRet, vKey2); + + // rounds 12-13 + __ load_word_vector_unaligned(vKey1, 176, key, tmp); + __ load_word_vector_unaligned(vKey2, 192, key, tmp); + + __ cmpwi (CR0, keylen, 52); // AES-192 -> final rounds + __ beq (CR0, L_doLast); +#ifdef ASSERT + __ cmpwi (CR0, keylen, 60); + __ asm_assert_eq(FILE_AND_LINE ": aes_encrypt_rounds - invalid key length"); +#endif + + __ vcipher (vRet, vRet, vKey1); + __ vcipher (vRet, vRet, vKey2); + + // rounds 14-15 + __ load_word_vector_unaligned(vKey1, 208, key, tmp); + __ load_word_vector_unaligned(vKey2, 224, key, tmp); + + __ bind(L_doLast); + __ vcipher (vRet, vRet, vKey1); + __ vcipherlast (vRet, vRet, vKey2); + } + + + // ========================================================================== + // Emits the AES decrypt round instructions. + // + // vRet: in/out — the AES state (ciphertext in, plaintext out) + // key: register holding pointer to expanded key array + // keylen: register holding key length (44/52/60) + // + void aes_decrypt_rounds(VectorRegister vRet, + Register key, Register keylen, Register tmp, + VectorRegister vKey1, VectorRegister vKey2, + VectorRegister vKey3, VectorRegister vKey4, + VectorRegister vKey5) { + Label L_doLast, L_do44, L_do52; + + __ cmpwi (CR0, keylen, 44); + __ beq (CR0, L_do44); + + __ cmpwi (CR0, keylen, 52); + __ beq (CR0, L_do52); + +#ifdef ASSERT + __ cmpwi (CR0, keylen, 60); + __ asm_assert_eq(FILE_AND_LINE ": aes_decrypt_rounds - invalid key length"); +#endif + // ---- AES-256: round keys 15-11 ---- + __ load_word_vector_unaligned(vKey1, 224, key, tmp); + __ load_word_vector_unaligned(vKey2, 208, key, tmp); + __ load_word_vector_unaligned(vKey3, 192, key, tmp); + __ load_word_vector_unaligned(vKey4, 176, key, tmp); + __ load_word_vector_unaligned(vKey5, 160, key, tmp); + + __ vxor (vRet, vRet, vKey1); + __ vncipher (vRet, vRet, vKey2); + __ vncipher (vRet, vRet, vKey3); + __ vncipher (vRet, vRet, vKey4); + __ vncipher (vRet, vRet, vKey5); + __ b (L_doLast); + + __ align(32); + // ---- AES-192: round keys 13-11 ---- + __ bind (L_do52); + __ load_word_vector_unaligned(vKey1, 192, key, tmp); + __ load_word_vector_unaligned(vKey2, 176, key, tmp); + __ load_word_vector_unaligned(vKey3, 160, key, tmp); + + __ vxor (vRet, vRet, vKey1); + __ vncipher (vRet, vRet, vKey2); + __ vncipher (vRet, vRet, vKey3); + __ b (L_doLast); + + __ align(32); + // ---- AES-128: round key 11 ---- + __ bind (L_do44); + __ load_word_vector_unaligned(vKey1, 160, key, tmp); + __ vxor (vRet, vRet, vKey1); + + // ---- Common rounds 10-1 ---- + __ bind (L_doLast); + __ load_word_vector_unaligned(vKey1, 144, key, tmp); + __ load_word_vector_unaligned(vKey2, 128, key, tmp); + __ load_word_vector_unaligned(vKey3, 112, key, tmp); + __ load_word_vector_unaligned(vKey4, 96, key, tmp); + __ load_word_vector_unaligned(vKey5, 80, key, tmp); + + __ vncipher (vRet, vRet, vKey1); + __ vncipher (vRet, vRet, vKey2); + __ vncipher (vRet, vRet, vKey3); + __ vncipher (vRet, vRet, vKey4); + __ vncipher (vRet, vRet, vKey5); + __ load_word_vector_unaligned(vKey1, 64, key, tmp); + __ load_word_vector_unaligned(vKey2, 48, key, tmp); + __ load_word_vector_unaligned(vKey3, 32, key, tmp); + __ load_word_vector_unaligned(vKey4, 16, key, tmp); + __ load_word_vector_unaligned(vKey5, 0, key, tmp); + __ vncipher (vRet, vRet, vKey1); + __ vncipher (vRet, vRet, vKey2); + __ vncipher (vRet, vRet, vKey3); + __ vncipher (vRet, vRet, vKey4); + __ vncipherlast (vRet, vRet, vKey5); + } + + // ========================================================================== + // CBC Encrypt stub — using helper functions + // from: R3_ARG1 - source byte array address (plaintext) + // to: R4_ARG2 - destination byte array address (ciphertext) + // key: R5_ARG3 - round key array + // rvec: R6_ARG4 - r vector byte array address (initialization vector) + // input_len: R7_ARG5 - length of input in bytes + // + // Returns: + // R3_RET - number of bytes processed + // + address generate_cipherBlockChaining_encryptAESCrypt() { + assert(UseAESIntrinsics, "need AES instructions support"); + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; + StubCodeMark mark(this, stub_id); + + address start = __ function_entry(); + + Label L_enc_loop; + + Register from = R3_ARG1; + Register to = R4_ARG2; + Register key = R5_ARG3; + Register rvec = R6_ARG4; + Register input_len = R7_ARG5; + + Register keylen = R8; + Register tmp = R9; + Register len = R10; + + VectorRegister vRet = VR0; + VectorRegister vKey1 = VR1; + VectorRegister vKey2 = VR2; + VectorRegister vKey3 = VR3; + VectorRegister vKey4 = VR4; + VectorRegister vIn = VR5; + VectorRegister vp = VR6; // permute vector for P8 LE byte accesses + VectorRegister vTmp = VR7; + + __ mr (len, input_len); + + // vp must be computed once, before any byte vector access. Clobbers R0. + __ compute_vp_for_byte_vector_unaligned(vp, /*temp*/ vRet); + + __ load_byte_vector_unaligned(vRet, 0, rvec, tmp, vp); + + __ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - + arrayOopDesc::base_offset_in_bytes(T_INT), key); + + __ align(32); + __ bind(L_enc_loop); + __ load_byte_vector_unaligned(vIn, 0, from, tmp, vp); + __ addi (from, from, 16); + __ vxor (vRet, vRet, vIn); // CBC XOR + aes_encrypt_rounds(vRet, key, keylen, tmp, vKey1, vKey2, vKey3, vKey4); + __ store_byte_vector_unaligned(vRet, 0, to, tmp, vp, vTmp); + __ addi (to, to, 16); + __ addic_ (len, len, -16); + __ bne (CR0, L_enc_loop); + + // save the last ciphertext block in rvec; it is the IV for the next call + __ store_byte_vector_unaligned(vRet, 0, rvec, tmp, vp, vTmp); + __ mr (R3_RET, input_len); + __ blr(); + + return start; + } + + // ========================================================================== + // CBC Decrypt stub + // Arguments: + // R3_ARG1 - from: source byte array address (ciphertext) + // R4_ARG2 - to: destination byte array address (plaintext) + // R5_ARG3 - key: round key array + // R6_ARG4 - rvec: r vector byte array address (in/out), holds the + // initialization vector on entry and is updated with + // the last ciphertext block on exit + // R7_ARG5 - input_len: length of input in bytes, a multiple of 16 + // + // Returns: + // R3_RET - number of bytes processed + // ========================================================================== + + address generate_cipherBlockChaining_decryptAESCrypt() { + assert(UseAESIntrinsics, "need AES instructions support"); + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; + StubCodeMark mark(this, stub_id); + + address start = __ function_entry(); + + Label L_dec_loop; + + Register from = R3_ARG1; + Register to = R4_ARG2; + Register key = R5_ARG3; + Register rvec = R6_ARG4; + Register input_len = R7_ARG5; + + Register keylen = R8; + Register tmp = R9; + Register len = R10; + + VectorRegister vRet = VR0; + VectorRegister vKey1 = VR1; + VectorRegister vKey2 = VR2; + VectorRegister vKey3 = VR3; + VectorRegister vKey4 = VR4; + VectorRegister vKey5 = VR5; + VectorRegister vIV = VR6; + VectorRegister vSavedCT = VR7; + VectorRegister vp = VR8; // permute vector for P8 LE byte accesses + VectorRegister vTmp = VR9; + __ mr (len, input_len); + // vp must be computed before any byte vector access. Clobbers R0. + __ compute_vp_for_byte_vector_unaligned(vp, /*temp*/ vRet); + + __ load_byte_vector_unaligned(vIV, 0, rvec, tmp, vp); + + __ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - + arrayOopDesc::base_offset_in_bytes(T_INT), key); + + __ align(32); + __ bind(L_dec_loop); + __ load_byte_vector_unaligned(vRet, 0, from, tmp, vp); + __ addi (from, from, 16); + __ vor (vSavedCT, vRet, vRet); // AES will destroy vRet + aes_decrypt_rounds(vRet, key, keylen, tmp, vKey1, vKey2, vKey3, vKey4, vKey5); + __ vxor (vRet, vRet, vIV); // CBC XOR (after decrypt) + __ vor (vIV, vSavedCT, vSavedCT); // IV = previous ciphertext + __ store_byte_vector_unaligned(vRet, 0, to, tmp, vp, vTmp); + __ addi (to, to, 16); + __ addic_ (len, len, -16); + __ bne (CR0, L_dec_loop); + + __ store_byte_vector_unaligned(vIV, 0, rvec, tmp, vp, vTmp); + __ mr (R3_RET, input_len); + __ blr(); + + return start; + } + address generate_sha256_implCompress(StubId stub_id) { assert(UseSHA, "need SHA instructions"); bool multi_block; @@ -3742,7 +3840,8 @@ class StubGenerator: public StubCodeGenerator { address generate_floatToFloat16() { __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", "floatToFloat16"); + StubId stub_id = StubId::stubgen_f2hf_id; + StubCodeMark mark(this, stub_id); address start = __ function_entry(); __ f2hf(R3_RET, F1_ARG1, F0); __ blr(); @@ -3751,7 +3850,8 @@ class StubGenerator: public StubCodeGenerator { address generate_float16ToFloat() { __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", "float16ToFloat"); + StubId stub_id = StubId::stubgen_hf2f_id; + StubCodeMark mark(this, stub_id); address start = __ function_entry(); __ hf2f(F1_RET, R3_ARG1); __ blr(); @@ -5092,6 +5192,8 @@ void generate_lookup_secondary_supers_table_stub() { if (UseAESIntrinsics) { StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock(); StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock(); + StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt(); + StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt(); } if (UseSHA256Intrinsics) { diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index 35042e841e66..69ff7c2a6a65 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -1162,7 +1162,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); __ blr(); - __ flush(); + __ invalidate_icache(); return entry; } @@ -1179,7 +1179,7 @@ address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); __ blr(); - __ flush(); + __ invalidate_icache(); return entry; } @@ -1200,7 +1200,7 @@ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); __ blr(); - __ flush(); + __ invalidate_icache(); return entry; } @@ -1487,7 +1487,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // We use release_store_fence to update values like the thread state, where // we don't want the current thread to continue until all our prior memory // accesses (including the new thread state) are visible to other threads. - __ li(R0/*thread_state*/, _thread_in_vm); + __ li(R0/*thread_state*/, _thread_in_Java); __ release(); __ stw(R0/*thread_state*/, thread_(thread_state)); if (!UseSystemMemoryBarrier) { @@ -1498,10 +1498,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // (a new safepoint can not start since we entered _thread_in_vm). // We must check here because a current safepoint could be in progress. - // Acquire isn't strictly necessary here because of the fence, but - // sync_state is declared to be volatile, so we do it anyway - // (cmp-br-isync on one path, release (same as acquire on PPC64) on the other path). - Label do_safepoint, sync_check_done; // No synchronization in progress nor yet synchronized. __ safepoint_poll(do_safepoint, sync_state, true /* at_return */, false /* in_nmethod */); @@ -1513,13 +1509,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ beq(CR1, sync_check_done); __ bind(do_safepoint); - __ isync(); // Block. We do the call directly and leave the current // last_Java_frame setup undisturbed. We must save any possible // native result across the call. No oop is present. __ mr(R3_ARG1, R16_thread); - __ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ call_c(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); __ bind(sync_check_done); @@ -1540,14 +1535,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // On PPC64, we have stored the result directly after the native call. //============================================================================= - // Back in Java - - // We use release_store_fence to update values like the thread state, where - // we don't want the current thread to continue until all our prior memory - // accesses (including the new thread state) are visible to other threads. - __ li(R0/*thread_state*/, _thread_in_Java); - __ lwsync(); // Acquire safepoint and suspend state, release thread state. - __ stw(R0/*thread_state*/, thread_(thread_state)); if (support_vthread_preemption) { // Check preemption for Object.wait() diff --git a/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp index ae5410b12dfc..7d0cfeaea094 100644 --- a/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2023, 2025 SAP SE. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,7 +243,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, ////////////////////////////////////////////////////////////////////////////// - _masm->flush(); + // Code will be copied. No ICache sync required. #ifndef PRODUCT stringStream ss; diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 8781230d8126..b3b433cea948 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -514,7 +514,7 @@ void VM_Version::determine_features() { a->blr(); uint32_t *code_end = (uint32_t *)a->pc(); - a->flush(); + a->invalidate_icache(); _features = VM_Version::unknown_m; // Print the detection code. @@ -570,7 +570,7 @@ void VM_Version::config_dscr() { a->blr(); uint32_t *code_end = (uint32_t *)a->pc(); - a->flush(); + a->invalidate_icache(); // Print the detection code. if (PrintAssembly) { diff --git a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp index 73a1cbe090f8..b34f60cdec95 100644 --- a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,7 +124,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) __ mtctr(R12_scratch2); __ bctr(); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); return s; @@ -224,7 +224,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) __ mtctr(R11_scratch1); __ bctr(); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); return s; diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index b657c1f108dd..a689107493b1 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -514,20 +514,138 @@ class Assembler : public AbstractAssembler { rdy = 0b111, // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid. }; + // Efficient reading and writing of unaligned data in platform-specific byte ordering + // RISC-V needs to check for alignment. + + static inline u2 get_native_u2(address p) { + if ((intptr_t(p) & 1) == 0) { + return *(u2*)p; + } else { + return ((u2)(p[1]) << 8) | + ((u2)(p[0])); + } + } + + static inline u4 get_native_u4(address p) { + switch (intptr_t(p) & 3) { + case 0: + return *(u4*)p; + + case 2: + return ((u4)(((u2*)p)[1]) << 16) | + ((u4)(((u2*)p)[0])); + + default: + return ((u4)(p[3]) << 24) | + ((u4)(p[2]) << 16) | + ((u4)(p[1]) << 8) | + ((u4)(p[0])); + } + } + + static inline u8 get_native_u8(address p) { + switch (intptr_t(p) & 7) { + case 0: + return *(u8*)p; + + case 4: + return ((u8)(((u4*)p)[1]) << 32) | + ((u8)(((u4*)p)[0])); + + case 2: + case 6: + return ((u8)(((u2*)p)[3]) << 48) | + ((u8)(((u2*)p)[2]) << 32) | + ((u8)(((u2*)p)[1]) << 16) | + ((u8)(((u2*)p)[0])); + + default: + return ((u8)(p[7]) << 56) | + ((u8)(p[6]) << 48) | + ((u8)(p[5]) << 40) | + ((u8)(p[4]) << 32) | + ((u8)(p[3]) << 24) | + ((u8)(p[2]) << 16) | + ((u8)(p[1]) << 8) | + ((u8)(p[0])); + } + } + + static inline void put_native_u2(address p, u2 x) { + if ((intptr_t(p) & 1) == 0) { + *(u2*)p = x; + } else { + p[1] = x >> 8; + p[0] = x; + } + } + + static inline void put_native_u4(address p, u4 x) { + switch (intptr_t(p) & 3) { + case 0: + *(u4*)p = x; + break; + + case 2: + ((u2*)p)[1] = x >> 16; + ((u2*)p)[0] = x; + break; + + default: + ((u1*)p)[3] = x >> 24; + ((u1*)p)[2] = x >> 16; + ((u1*)p)[1] = x >> 8; + ((u1*)p)[0] = x; + break; + } + } + + static inline void put_native_u8(address p, u8 x) { + switch (intptr_t(p) & 7) { + case 0: + *(u8*)p = x; + break; + + case 4: + ((u4*)p)[1] = x >> 32; + ((u4*)p)[0] = x; + break; + + case 2: + case 6: + ((u2*)p)[3] = x >> 48; + ((u2*)p)[2] = x >> 32; + ((u2*)p)[1] = x >> 16; + ((u2*)p)[0] = x; + break; + + default: + ((u1*)p)[7] = x >> 56; + ((u1*)p)[6] = x >> 48; + ((u1*)p)[5] = x >> 40; + ((u1*)p)[4] = x >> 32; + ((u1*)p)[3] = x >> 24; + ((u1*)p)[2] = x >> 16; + ((u1*)p)[1] = x >> 8; + ((u1*)p)[0] = x; + break; + } + } + // handle unaligned access static inline uint16_t ld_c_instr(address addr) { - return Bytes::get_native_u2(addr); + return get_native_u2(addr); } static inline void sd_c_instr(address addr, uint16_t c_instr) { - Bytes::put_native_u2(addr, c_instr); + put_native_u2(addr, c_instr); } // handle unaligned access static inline uint32_t ld_instr(address addr) { - return Bytes::get_native_u4(addr); + return get_native_u4(addr); } static inline void sd_instr(address addr, uint32_t instr) { - Bytes::put_native_u4(addr, instr); + put_native_u4(addr, instr); } static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) { diff --git a/src/hotspot/cpu/riscv/bytes_riscv.hpp b/src/hotspot/cpu/riscv/bytes_riscv.hpp deleted file mode 100644 index 9495703a03f8..000000000000 --- a/src/hotspot/cpu/riscv/bytes_riscv.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. - * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * 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 CPU_RISCV_BYTES_RISCV_HPP -#define CPU_RISCV_BYTES_RISCV_HPP - -#include "memory/allStatic.hpp" -#include "utilities/byteswap.hpp" - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - // RISCV needs to check for alignment. - - static inline u2 get_native_u2(address p) { - if ((intptr_t(p) & 1) == 0) { - return *(u2*)p; - } else { - return ((u2)(p[1]) << 8) | - ((u2)(p[0])); - } - } - - static inline u4 get_native_u4(address p) { - switch (intptr_t(p) & 3) { - case 0: - return *(u4*)p; - - case 2: - return ((u4)(((u2*)p)[1]) << 16) | - ((u4)(((u2*)p)[0])); - - default: - return ((u4)(p[3]) << 24) | - ((u4)(p[2]) << 16) | - ((u4)(p[1]) << 8) | - ((u4)(p[0])); - } - } - - static inline u8 get_native_u8(address p) { - switch (intptr_t(p) & 7) { - case 0: - return *(u8*)p; - - case 4: - return ((u8)(((u4*)p)[1]) << 32) | - ((u8)(((u4*)p)[0])); - - case 2: - case 6: - return ((u8)(((u2*)p)[3]) << 48) | - ((u8)(((u2*)p)[2]) << 32) | - ((u8)(((u2*)p)[1]) << 16) | - ((u8)(((u2*)p)[0])); - - default: - return ((u8)(p[7]) << 56) | - ((u8)(p[6]) << 48) | - ((u8)(p[5]) << 40) | - ((u8)(p[4]) << 32) | - ((u8)(p[3]) << 24) | - ((u8)(p[2]) << 16) | - ((u8)(p[1]) << 8) | - ((u8)(p[0])); - } - } - - static inline void put_native_u2(address p, u2 x) { - if ((intptr_t(p) & 1) == 0) { - *(u2*)p = x; - } else { - p[1] = x >> 8; - p[0] = x; - } - } - - static inline void put_native_u4(address p, u4 x) { - switch (intptr_t(p) & 3) { - case 0: - *(u4*)p = x; - break; - - case 2: - ((u2*)p)[1] = x >> 16; - ((u2*)p)[0] = x; - break; - - default: - ((u1*)p)[3] = x >> 24; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[0] = x; - break; - } - } - - static inline void put_native_u8(address p, u8 x) { - switch (intptr_t(p) & 7) { - case 0: - *(u8*)p = x; - break; - - case 4: - ((u4*)p)[1] = x >> 32; - ((u4*)p)[0] = x; - break; - - case 2: - case 6: - ((u2*)p)[3] = x >> 48; - ((u2*)p)[2] = x >> 32; - ((u2*)p)[1] = x >> 16; - ((u2*)p)[0] = x; - break; - - default: - ((u1*)p)[7] = x >> 56; - ((u1*)p)[6] = x >> 48; - ((u1*)p)[5] = x >> 40; - ((u1*)p)[4] = x >> 32; - ((u1*)p)[3] = x >> 24; - ((u1*)p)[2] = x >> 16; - ((u1*)p)[1] = x >> 8; - ((u1*)p)[0] = x; - break; - } - } - -#ifndef VM_LITTLE_ENDIAN -#error RISC-V is little endian, the preprocessor macro VM_LITTLE_ENDIAN should be defined. -#endif - - // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) - static inline u2 get_Java_u2(address p) { return byteswap(get_native_u2(p)); } - static inline u4 get_Java_u4(address p) { return byteswap(get_native_u4(p)); } - static inline u8 get_Java_u8(address p) { return byteswap(get_native_u8(p)); } - - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, byteswap(x)); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, byteswap(x)); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, byteswap(x)); } -}; - -#endif // CPU_RISCV_BYTES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 496e26d3c0b5..b2473a9356e5 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -1262,13 +1262,8 @@ void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // We are storing into an array that *may* be null-free (the declared type is // Object[], abstract[], interface[] or VT.ref[]). - Label test_mark_word; Register tmp = op->tmp()->as_register(); __ ld(tmp, Address(op->array()->as_register(), oopDesc::mark_offset_in_bytes())); - __ test_bit(t0, tmp, exact_log2(markWord::unlocked_value)); - __ bnez(t0, test_mark_word); - __ load_prototype_header(tmp, op->array()->as_register()); - __ bind(test_mark_word); __ test_bit(tmp, tmp, exact_log2(markWord::null_free_array_bit_in_place)); } diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index c0504ba23da7..c2684982c140 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -123,8 +123,8 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a la"); // Try to lock. Transition lock-bits 0b01 => 0b00 - ori(tmp1_mark, tmp1_mark, markWord::unlocked_value); - xori(tmp3_t, tmp1_mark, markWord::unlocked_value); + ori(tmp1_mark, tmp1_mark, markWord::lock_neutral_value); + xori(tmp3_t, tmp1_mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ tmp1_mark, /*new*/ tmp3_t, Assembler::int64, /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ tmp3_t); bne(tmp1_mark, tmp3_t, slow_path); @@ -295,7 +295,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register box, // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); - ori(tmp3_t, tmp1_mark, markWord::unlocked_value); + ori(tmp3_t, tmp1_mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ tmp1_mark, /*new*/ tmp3_t, Assembler::int64, /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, /*result*/ tmp3_t); beq(tmp1_mark, tmp3_t, unlocked); @@ -408,6 +408,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register box, // StringLatin1.indexOfChar void C2_MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, Register ch, Register result, + Register start_index, bool isL) { Register ch1 = t0; @@ -500,7 +501,7 @@ void C2_MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, addi(index, index, 7); bind(MATCH); - mv(result, index); + add(result, start_index, index); bind(NOMATCH); BLOCK_COMMENT("} string_indexof_char_short"); } @@ -513,39 +514,40 @@ void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, Register tmp3, Register tmp4, bool isL) { - Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; + Label CH1_LOOP, HIT, DONE, SHORT; Register ch1 = t0; Register orig_cnt = t1; - Register mask1 = tmp3; + Register mask1 = tmp1; Register mask2 = tmp2; - Register match_mask = tmp1; - Register trailing_char = tmp4; - Register unaligned_elems = tmp4; + Register match_mask = tmp3; + Register loop_step = tmp4; + Register trailing_chars = tmp4; + Register unaligned_chars = tmp4; + Register start_index = tmp4; BLOCK_COMMENT("string_indexof_char {"); - beqz(cnt1, NOMATCH); + mv(result, -1); + beqz(cnt1, DONE); subi(t0, cnt1, isL ? 32 : 16); - bgtz(t0, DO_LONG); - string_indexof_char_short(str1, cnt1, ch, result, isL); - j(DONE); + mv(start_index, zr); + blez(t0, SHORT); - bind(DO_LONG); mv(orig_cnt, cnt1); if (AvoidUnalignedAccesses) { Label ALIGNED; - andi(unaligned_elems, str1, 0x7); - beqz(unaligned_elems, ALIGNED); - sub(unaligned_elems, unaligned_elems, 8); - neg(unaligned_elems, unaligned_elems); + andi(unaligned_chars, str1, 0x7); + beqz(unaligned_chars, ALIGNED); + sub(unaligned_chars, unaligned_chars, 8); + neg(unaligned_chars, unaligned_chars); if (!isL) { - srli(unaligned_elems, unaligned_elems, 1); + srli(unaligned_chars, unaligned_chars, 1); } // do unaligned part per element - string_indexof_char_short(str1, unaligned_elems, ch, result, isL); + string_indexof_char_short(str1, unaligned_chars, ch, result, zr, isL); bgez(result, DONE); mv(orig_cnt, cnt1); - sub(cnt1, cnt1, unaligned_elems); + sub(cnt1, cnt1, unaligned_chars); bind(ALIGNED); } @@ -570,33 +572,47 @@ void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); mv(mask2, isL ? mask7f7f : mask7fff); + mv(loop_step, 8); + bind(CH1_LOOP); ld(ch1, Address(str1)); - addi(str1, str1, 8); - subi(cnt1, cnt1, 8); compute_match_mask(ch1, ch, match_mask, mask1, mask2); bnez(match_mask, HIT); - bgtz(cnt1, CH1_LOOP); - j(NOMATCH); + addi(str1, str1, 8); + subi(cnt1, cnt1, 8); + bge(cnt1, loop_step, CH1_LOOP); + + beqz(cnt1, DONE); + if (!isL) { + srli(cnt1, cnt1, 1); + } + // Tail (1..7 chars) after the SWAR loop has advanced str1. cnt1 holds the + // remaining char count; the number of chars already scanned by the loop is + // (orig_cnt - cnt1). string_indexof_char_short returns an index relative to + // the current str1, so we pass that prefix as start_index to recover the + // real index. + // Note: ch was broadcast across all 8 bytes for the SWAR loop above, but the + // short helper compares a single element, so restore ch to a single char. + isL ? zext(ch, ch, 8) : zext(ch, ch, 16); + sub(start_index, orig_cnt, cnt1); + + bind(SHORT); + string_indexof_char_short(str1, cnt1, ch, result, start_index, isL); + j(DONE); bind(HIT); // count bits of trailing zero chars - ctzc_bits(trailing_char, match_mask, isL, ch1, result); - srli(trailing_char, trailing_char, 3); - addi(cnt1, cnt1, 8); - ble(cnt1, trailing_char, NOMATCH); + ctzc_bits(trailing_chars, match_mask, isL, mask1, mask2); + srli(trailing_chars, trailing_chars, 3); + // match case if (!isL) { srli(cnt1, cnt1, 1); - srli(trailing_char, trailing_char, 1); + srli(trailing_chars, trailing_chars, 1); } sub(result, orig_cnt, cnt1); - add(result, result, trailing_char); - j(DONE); - - bind(NOMATCH); - mv(result, -1); + add(result, result, trailing_chars); bind(DONE); BLOCK_COMMENT("} string_indexof_char"); diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp index db80d048e927..8fea474dacb2 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -64,6 +64,7 @@ void string_indexof_char_short(Register str1, Register cnt1, Register ch, Register result, + Register start_index, bool isL); void string_indexof_char(Register str1, Register cnt1, diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index b11abb912ee5..e1511f5b7f34 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -304,12 +304,14 @@ void DowncallLinker::StubGenerator::generate() { Label L_reguard; Label L_after_reguard; if (_needs_transition) { + __ block_comment("{ thread native2java"); // Restore cpu control state after JNI call __ restore_cpu_control_state_after_jni(t0); - __ block_comment("{ thread native2java"); - __ mv(t0, _thread_in_vm); - __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + // change thread state + __ mv(t1, _thread_in_Java); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sw(t1, Address(xthread, JavaThread::thread_state_offset())); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -322,11 +324,6 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_after_safepoint_poll); - // change thread state - __ mv(t0, _thread_in_Java); - __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); - __ block_comment("reguard stack check"); __ lbu(t0, Address(xthread, JavaThread::stack_guard_state_offset())); __ mv(t1, StackOverflow::stack_guard_yellow_reserved_disabled); @@ -353,7 +350,7 @@ void DowncallLinker::StubGenerator::generate() { __ mv(c_rarg0, xthread); assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); - __ rt_call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, out_spill_offset); @@ -383,5 +380,5 @@ void DowncallLinker::StubGenerator::generate() { ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. } diff --git a/src/hotspot/cpu/riscv/gc/z/z_riscv.ad b/src/hotspot/cpu/riscv/gc/z/z_riscv.ad index 0078deb76e8c..a922f5337b2c 100644 --- a/src/hotspot/cpu/riscv/gc/z/z_riscv.ad +++ b/src/hotspot/cpu/riscv/gc/z/z_riscv.ad @@ -33,7 +33,7 @@ source_hpp %{ source %{ #include "gc/z/zBarrierSetAssembler.hpp" -static void z_color(MacroAssembler* masm, const MachNode* node, Register dst, Register src, Register tmp) { +static void z_color(MacroAssembler* masm, Register dst, Register src, Register tmp) { assert_different_registers(dst, tmp); __ relocate(barrier_Relocation::spec(), [&] { @@ -43,7 +43,7 @@ static void z_color(MacroAssembler* masm, const MachNode* node, Register dst, Re __ orr(dst, dst, tmp); } -static void z_uncolor(MacroAssembler* masm, const MachNode* node, Register ref) { +static void z_uncolor(MacroAssembler* masm, Register ref) { __ srli(ref, ref, ZPointerLoadShift); } @@ -63,7 +63,7 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r ((node->barrier_data() & ZBarrierPhantom) != 0); if (node->barrier_data() == ZBarrierElided) { - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); return; } @@ -74,14 +74,14 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r __ j(*stub->entry()); __ bind(good); - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); __ bind(*stub->continuation()); } static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) { Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); if (node->barrier_data() == ZBarrierElided) { - z_color(masm, node, rnew_zpointer, rnew_zaddress, tmp); + z_color(masm, rnew_zpointer, rnew_zaddress, tmp); } else { bool is_native = (node->barrier_data() & ZBarrierNative) != 0; bool is_nokeepalive = (node->barrier_data() & ZBarrierNoKeepalive) != 0; @@ -145,7 +145,7 @@ instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newva ins_encode %{ guarantee($mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, $tmp1$$Register, true /* is_atomic */); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::int64, Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, true /* result_as_bool */); %} @@ -168,7 +168,7 @@ instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne ins_encode %{ guarantee($mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, $tmp1$$Register, true /* is_atomic */); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::int64, Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, true /* result_as_bool */); %} @@ -189,10 +189,10 @@ instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP n ins_encode %{ guarantee($mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, $tmp1$$Register, true /* is_atomic */); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::int64, Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); - z_uncolor(masm, this, $res$$Register); + z_uncolor(masm, $res$$Register); %} ins_pipe(pipe_slow); @@ -211,10 +211,10 @@ instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iReg ins_encode %{ guarantee($mem$$disp == 0, "impossible encoding"); Address ref_addr($mem$$Register); - z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); + z_color(masm, $oldval_tmp$$Register, $oldval$$Register, $tmp1$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, $tmp1$$Register, true /* is_atomic */); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::int64, Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); - z_uncolor(masm, this, $res$$Register); + z_uncolor(masm, $res$$Register); %} ins_pipe(pipe_slow); @@ -232,7 +232,7 @@ instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, iRegPNoSp tmp, rF ins_encode %{ z_store_barrier(masm, this, Address($mem$$Register), $newv$$Register, $prev$$Register, $tmp$$Register, true /* is_atomic */); __ atomic_xchg($prev$$Register, $prev$$Register, $mem$$Register); - z_uncolor(masm, this, $prev$$Register); + z_uncolor(masm, $prev$$Register); %} ins_pipe(pipe_serial); @@ -250,7 +250,7 @@ instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, iRegPNoSp tmp, ins_encode %{ z_store_barrier(masm, this, Address($mem$$Register), $newv$$Register, $prev$$Register, $tmp$$Register, true /* is_atomic */); __ atomic_xchgal($prev$$Register, $prev$$Register, $mem$$Register); - z_uncolor(masm, this, $prev$$Register); + z_uncolor(masm, $prev$$Register); %} ins_pipe(pipe_serial); %} diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp index c8e488d9d691..fc9f224a7675 100644 --- a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -168,7 +168,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin __ movptr(x10, ExternalAddress(Interpreter::result_handler(method()->result_type()))); __ ret(); - __ flush(); + __ invalidate_icache(); } diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp index 9755cb9ef16c..dcdbe4a6dc18 100644 --- a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp +++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp @@ -166,7 +166,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { __ leave(); __ ret(); } - __ flush(); + __ invalidate_icache(); return fast_entry; } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index ec044b6f824d..2f44cf42dc37 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -162,8 +162,7 @@ uint32_t MacroAssembler::get_membar_kind(address addr) { assert_cond(addr != nullptr); assert(is_membar(addr), "no membar found"); - uint32_t insn = Bytes::get_native_u4(addr); - + uint32_t insn = Assembler::ld_instr(addr); uint32_t predecessor = Assembler::extract(insn, 27, 24); uint32_t successor = Assembler::extract(insn, 23, 20); @@ -179,7 +178,7 @@ void MacroAssembler::set_membar_kind(address addr, uint32_t order_kind) { MacroAssembler::membar_mask_to_pred_succ(order_kind, predecessor, successor); - uint32_t insn = Bytes::get_native_u4(addr); + uint32_t insn = Assembler::ld_instr(addr); address pInsn = (address) &insn; Assembler::patch(pInsn, 27, 24, predecessor); Assembler::patch(pInsn, 23, 20, successor); @@ -3844,11 +3843,17 @@ void MacroAssembler::encode_heap_oop(Register d, Register s) { mv(d, s); } } else { - Label notNull; - sub(d, s, xheapbase); - bgez(d, notNull); - mv(d, zr); - bind(notNull); + if (UseZicond) { + assert_different_registers(s, t0); + sub(t0, s, xheapbase); + czero_eqz(d, t0, s); // d = s == 0 ? 0 : t0 + } else { + Label notNull; + sub(d, s, xheapbase); + bgez(d, notNull); + mv(d, zr); + bind(notNull); + } if (CompressedOops::shift() != 0) { assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); srli(d, d, CompressedOops::shift()); @@ -3922,11 +3927,6 @@ void MacroAssembler::load_klass(Register dst, Register src, Register tmp) { decode_klass_not_null(dst, tmp); } -void MacroAssembler::load_prototype_header(Register dst, Register src, Register tmp) { - load_klass(dst, src, tmp); - ld(dst, Address(dst, Klass::prototype_header_offset())); -} - void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { // FIXME: Should this be a store release? concurrent gcs assumes // klass length is valid if klass field is not null. @@ -4060,11 +4060,18 @@ void MacroAssembler::decode_heap_oop(Register d, Register s) { slli(d, s, CompressedOops::shift()); } } else { - Label done; - mv(d, s); - beqz(s, done); - shadd(d, s, xheapbase, d, LogMinObjAlignmentInBytes); - bind(done); + assert(LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); + if (UseZicond) { + assert_different_registers(s, t0); + shadd(t0, s, xheapbase, t0, LogMinObjAlignmentInBytes); + czero_eqz(d, t0, s); // d = s == 0 ? 0 : t0 + } else { + Label done; + mv(d, s); + beqz(s, done); + shadd(d, s, xheapbase, d, LogMinObjAlignmentInBytes); + bind(done); + } } verify_oop_msg(d, "broken oop in decode_heap_oop"); } @@ -7125,13 +7132,13 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register tmp1, // Try to lock. Transition lock-bits 0b01 => 0b00 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a la"); - ori(mark, mark, markWord::unlocked_value); + ori(mark, mark, markWord::lock_neutral_value); if (Arguments::is_valhalla_enabled()) { // Mask inline_type bit such that we go to the slow path if object is an inline type andi(mark, mark, ~((int) markWord::inline_type_bit_in_place)); } - xori(t, mark, markWord::unlocked_value); + xori(t, mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::int64, /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ t); bne(mark, t, slow, /* is_far */ true); @@ -7194,7 +7201,7 @@ void MacroAssembler::fast_unlock(Register obj, Register tmp1, Register tmp2, Reg #ifdef ASSERT // Check header not unlocked (0b01). Label not_unlocked; - test_bit(t, mark, exact_log2(markWord::unlocked_value)); + test_bit(t, mark, exact_log2(markWord::lock_neutral_value)); beqz(t, not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); @@ -7202,7 +7209,7 @@ void MacroAssembler::fast_unlock(Register obj, Register tmp1, Register tmp2, Reg // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); - ori(t, mark, markWord::unlocked_value); + ori(t, mark, markWord::lock_neutral_value); cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::int64, /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, /*result*/ t); beq(mark, t, unlocked); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 9af9fad06d08..be684c5ec908 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -201,7 +201,6 @@ class MacroAssembler: public Assembler { void access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); void load_klass(Register dst, Register src, Register tmp = t0); - void load_prototype_header(Register dst, Register src, Register tmp = t0); void load_narrow_klass_compact(Register dst, Register src); void load_narrow_klass(Register dst, Register src); void store_klass(Register dst, Register src, Register tmp = t0); @@ -1842,7 +1841,7 @@ class MacroAssembler: public Assembler { static bool is_pc_relative_at(address branch); static bool is_membar(address addr) { - return (Bytes::get_native_u4(addr) & 0x7f) == 0b1111 && extract_funct3(addr) == 0; + return (Assembler::ld_instr(addr) & 0x7f) == 0b1111 && extract_funct3(addr) == 0; } static uint32_t get_membar_kind(address addr); static void set_membar_kind(address addr, uint32_t order_kind); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 5d1cac72ade2..6f51395898a3 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -234,7 +234,7 @@ void NativeMovConstReg::verify() { intptr_t NativeMovConstReg::data() const { address addr = MacroAssembler::target_addr_for_insn(instruction_address()); if (maybe_cpool_ref(instruction_address())) { - return Bytes::get_native_u8(addr); + return MacroAssembler::get_native_u8(addr); } else { return (intptr_t)addr; } @@ -243,7 +243,7 @@ intptr_t NativeMovConstReg::data() const { void NativeMovConstReg::set_data(intptr_t x) { if (maybe_cpool_ref(instruction_address())) { address addr = MacroAssembler::target_addr_for_insn(instruction_address()); - Bytes::put_native_u8(addr, x); + MacroAssembler::put_native_u8(addr, x); } else { // Store x into the instruction stream. MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)x); @@ -259,11 +259,11 @@ void NativeMovConstReg::set_data(intptr_t x) { while (iter.next()) { if (iter.type() == relocInfo::oop_type) { oop* oop_addr = iter.oop_reloc()->oop_addr(); - Bytes::put_native_u8((address)oop_addr, x); + MacroAssembler::put_native_u8((address)oop_addr, x); break; } else if (iter.type() == relocInfo::metadata_type) { Metadata** metadata_addr = iter.metadata_reloc()->metadata_addr(); - Bytes::put_native_u8((address)metadata_addr, x); + MacroAssembler::put_native_u8((address)metadata_addr, x); break; } } diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index b28e33759b2f..90f32c9b25db 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -78,19 +78,19 @@ class NativeInstruction { protected: address addr_at(int offset) const { return address(this) + offset; } - jint int_at(int offset) const { return (jint) Bytes::get_native_u4(addr_at(offset)); } - juint uint_at(int offset) const { return Bytes::get_native_u4(addr_at(offset)); } - address ptr_at(int offset) const { return (address) Bytes::get_native_u8(addr_at(offset)); } - oop oop_at(int offset) const { return cast_to_oop(Bytes::get_native_u8(addr_at(offset))); } + jint int_at(int offset) const { return (jint) MacroAssembler::get_native_u4(addr_at(offset)); } + juint uint_at(int offset) const { return MacroAssembler::get_native_u4(addr_at(offset)); } + address ptr_at(int offset) const { return (address) MacroAssembler::get_native_u8(addr_at(offset)); } + oop oop_at(int offset) const { return cast_to_oop(MacroAssembler::get_native_u8(addr_at(offset))); } - void set_int_at(int offset, jint i) { Bytes::put_native_u4(addr_at(offset), i); } - void set_uint_at(int offset, jint i) { Bytes::put_native_u4(addr_at(offset), i); } - void set_ptr_at(int offset, address ptr) { Bytes::put_native_u8(addr_at(offset), (u8)ptr); } - void set_oop_at(int offset, oop o) { Bytes::put_native_u8(addr_at(offset), cast_from_oop(o)); } + void set_int_at(int offset, jint i) { MacroAssembler::put_native_u4(addr_at(offset), i); } + void set_uint_at(int offset, juint i) { MacroAssembler::put_native_u4(addr_at(offset), i); } + void set_ptr_at(int offset, address ptr) { MacroAssembler::put_native_u8(addr_at(offset), (u8)ptr); } + void set_oop_at(int offset, oop o) { MacroAssembler::put_native_u8(addr_at(offset), cast_from_oop(o)); } - static void set_data64_at(address dest, uint64_t data) { Bytes::put_native_u8(dest, (u8)data); } - static uint64_t get_data64_at(address src) { return Bytes::get_native_u8(src); } + static void set_data64_at(address dest, uint64_t data) { MacroAssembler::put_native_u8(dest, (u8)data); } + static uint64_t get_data64_at(address src) { return MacroAssembler::get_native_u8(src); } public: inline friend NativeInstruction* nativeInstruction_at(address addr); diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp index ccd8b8919969..09264327516e 100644 --- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp @@ -44,7 +44,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { if (MacroAssembler::is_load_pc_relative_at(addr())) { address constptr = (address)code()->oop_addr_at(reloc->oop_index()); bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); - assert((address)Bytes::get_native_u8(constptr) == x, "error in oop relocation"); + assert((address)MacroAssembler::get_native_u8(constptr) == x, "error in oop relocation"); } else { bytes = MacroAssembler::patch_oop(addr(), x); } diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 033e4a4222e0..f8b9acd18a90 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -2850,6 +2850,29 @@ operand immIpowerOf2() %{ interface(CONST_INTER); %} +// Int immediate: the mask of a bitfield extract, i.e. contiguous low-order +// ones, whose width is log2i_exact(mask + 1), e.g. 0xfff, 0xffff, 0x7fffffff. +// Masks that fit into a 12-bit immediate are excluded: a shift followed by +// andi is already as short as the shift pair used to extract the field. +operand immI_bitmask() %{ + predicate(is_power_of_2((juint)n->get_int() + 1) && + !Assembler::is_simm12((int64_t)n->get_int())); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: low 16-bit mask +operand immL_16bits() +%{ + predicate(n->get_long() == 0xFFFFL); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: low 32-bit mask operand immL_32bits() %{ @@ -2860,6 +2883,17 @@ operand immL_32bits() interface(CONST_INTER); %} +// Long immediate: the mask of a bitfield extract, see immI_bitmask above, +// e.g. 0xfff, 0xffffffff, 0x7fffffffffffffff. +operand immL_bitmask() %{ + predicate(is_power_of_2((julong)n->get_long() + 1) && + !Assembler::is_simm12(n->get_long())); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // 64 bit unit decrement operand immL_M1() %{ @@ -7254,6 +7288,86 @@ instruct urShiftP_reg_imm(iRegLNoSp dst, iRegP src1, immI src2) %{ ins_pipe(ialu_reg_shift); %} +// Unsigned bitfield extract: (src >>> rshift) & (2^width - 1) +instruct bitfieldExtractI(iRegINoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask) %{ + match(Set dst (AndI (URShiftI src rshift) mask)); + // The field must not extend past the high end of the int. + predicate(log2i_exact((juint)n->in(2)->get_int() + 1) + (n->in(1)->in(2)->get_int() & 0x1f) <= 32); + + ins_cost(ALU_COST * 2); + format %{ "slli $dst, $src, 64 - (($rshift & 0x1f) + width($mask))\n\t" + "srli $dst, $dst, 64 - width($mask)\t#@bitfieldExtractI" %} + + ins_encode %{ + int rshift = $rshift$$constant & 0x1f; + int width = log2i_exact((juint)$mask$$constant + 1); + __ slli(as_Register($dst$$reg), as_Register($src$$reg), 64 - (rshift + width)); + __ srli(as_Register($dst$$reg), as_Register($dst$$reg), 64 - width); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Unsigned bitfield extract from an int with a zero-extending conversion to long. +instruct bitfieldExtractI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask) %{ + match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask))); + predicate(log2i_exact((juint)n->in(1)->in(2)->get_int() + 1) + + (n->in(1)->in(1)->in(2)->get_int() & 0x1f) <= 32); + + ins_cost(ALU_COST * 2); + format %{ "slli $dst, $src, 64 - (($rshift & 0x1f) + width($mask))\n\t" + "srli $dst, $dst, 64 - width($mask)\t#@bitfieldExtractI2L" %} + + ins_encode %{ + int rshift = $rshift$$constant & 0x1f; + int width = log2i_exact((juint)$mask$$constant + 1); + __ slli(as_Register($dst$$reg), as_Register($src$$reg), 64 - (rshift + width)); + __ srli(as_Register($dst$$reg), as_Register($dst$$reg), 64 - width); + %} + + ins_pipe(ialu_reg_shift); +%} + +instruct bitfieldExtractL(iRegLNoSp dst, iRegL src, immI rshift, immL_bitmask mask) %{ + match(Set dst (AndL (URShiftL src rshift) mask)); + // The field must not extend past the high end of the long. + predicate(log2i_exact((julong)n->in(2)->get_long() + 1) + (n->in(1)->in(2)->get_int() & 0x3f) <= 64); + + ins_cost(ALU_COST * 2); + format %{ "slli $dst, $src, 64 - (($rshift & 0x3f) + width($mask))\n\t" + "srli $dst, $dst, 64 - width($mask)\t#@bitfieldExtractL" %} + + ins_encode %{ + int rshift = $rshift$$constant & 0x3f; + int width = log2i_exact((julong)$mask$$constant + 1); + __ slli(as_Register($dst$$reg), as_Register($src$$reg), 64 - (rshift + width)); + __ srli(as_Register($dst$$reg), as_Register($dst$$reg), 64 - width); + %} + + ins_pipe(ialu_reg_shift); +%} + +// Extract an int sized field out of a long. The mask is at most 31 bits wide, +// so the zero extended result is a valid int. This is the shape emitted by +// LibraryCallKit::inline_native_hashcode. +instruct bitfieldExtractL2I(iRegINoSp dst, iRegL src, immI rshift, immI_bitmask mask) %{ + match(Set dst (AndI (ConvL2I (URShiftL src rshift)) mask)); + predicate(log2i_exact((juint)n->in(2)->get_int() + 1) + (n->in(1)->in(1)->in(2)->get_int() & 0x3f) <= 64); + + ins_cost(ALU_COST * 2); + format %{ "slli $dst, $src, 64 - (($rshift & 0x3f) + width($mask))\n\t" + "srli $dst, $dst, 64 - width($mask)\t#@bitfieldExtractL2I" %} + + ins_encode %{ + int rshift = $rshift$$constant & 0x3f; + int width = log2i_exact((juint)$mask$$constant + 1); + __ slli(as_Register($dst$$reg), as_Register($src$$reg), 64 - (rshift + width)); + __ srli(as_Register($dst$$reg), as_Register($dst$$reg), 64 - width); + %} + + ins_pipe(ialu_reg_shift); +%} + // Shift Right Arithmetic Register // Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored. instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad index a13efa96fc16..cf61b1d43a6e 100644 --- a/src/hotspot/cpu/riscv/riscv_b.ad +++ b/src/hotspot/cpu/riscv/riscv_b.ad @@ -183,7 +183,37 @@ instruct convI2UL_reg_reg_b(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ __ zext_w(as_Register($dst$$reg), as_Register($src$$reg)); %} - ins_pipe(ialu_reg_shift); + ins_pipe(ialu_reg); +%} + +// And with a low 16-bit mask +instruct andL_16bits_b(iRegLNoSp dst, iRegL src, immL_16bits mask) %{ + predicate(UseZbb); + match(Set dst (AndL src mask)); + + format %{ "zext.h $dst, $src\t#@andL_16bits_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ zext_h(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); +%} + +// And with a low 32-bit mask +instruct andL_32bits_b(iRegLNoSp dst, iRegL src, immL_32bits mask) %{ + predicate(UseZba); + match(Set dst (AndL src mask)); + + format %{ "zext.w $dst, $src\t#@andL_32bits_b" %} + + ins_cost(ALU_COST); + ins_encode %{ + __ zext_w(as_Register($dst$$reg), as_Register($src$$reg)); + %} + + ins_pipe(ialu_reg); %} // BSWAP instructions diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index ef0ce89133ed..a4cd5c838715 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -4518,7 +4518,7 @@ instruct vmaskAllL(vRegMask dst, iRegL src) %{ // ------------------------------ Vector mask basic OPs ------------------------ -// vector mask logical ops: and/and-not/or/xor +// vector mask logical ops instruct vmask_and(vRegMask dst, vRegMask src1, vRegMask src2) %{ match(Set dst (AndVMask src1 src2)); @@ -4559,6 +4559,136 @@ instruct vmask_and_notL(vRegMask dst, vRegMask src1, vRegMask src2, immL_M1 m1) ins_pipe(pipe_slow); %} +instruct vmask_or_notI(vRegMask dst, vRegMask src1, vRegMask src2, immI_M1 m1) %{ + match(Set dst (OrVMask src1 (XorVMask src2 (MaskAll m1)))); + format %{ "vmask_or_notI $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmorn_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_or_notL(vRegMask dst, vRegMask src1, vRegMask src2, immL_M1 m1) %{ + match(Set dst (OrVMask src1 (XorVMask src2 (MaskAll m1)))); + format %{ "vmask_or_notL $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmorn_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_nandI(vRegMask dst, vRegMask src1, vRegMask src2, immI_M1 m1) %{ + match(Set dst (XorVMask (AndVMask src1 src2) (MaskAll m1))); + format %{ "vmask_nandI $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnand_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_nandL(vRegMask dst, vRegMask src1, vRegMask src2, immL_M1 m1) %{ + match(Set dst (XorVMask (AndVMask src1 src2) (MaskAll m1))); + format %{ "vmask_nandL $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnand_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_norI(vRegMask dst, vRegMask src1, vRegMask src2, immI_M1 m1) %{ + match(Set dst (XorVMask (OrVMask src1 src2) (MaskAll m1))); + format %{ "vmask_norI $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnor_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_norL(vRegMask dst, vRegMask src1, vRegMask src2, immL_M1 m1) %{ + match(Set dst (XorVMask (OrVMask src1 src2) (MaskAll m1))); + format %{ "vmask_norL $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnor_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_xnorI(vRegMask dst, vRegMask src1, vRegMask src2, immI_M1 m1) %{ + match(Set dst (XorVMask (XorVMask src1 src2) (MaskAll m1))); + match(Set dst (XorVMask src1 (XorVMask src2 (MaskAll m1)))); + format %{ "vmask_xnorI $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmxnor_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_xnorL(vRegMask dst, vRegMask src1, vRegMask src2, immL_M1 m1) %{ + match(Set dst (XorVMask (XorVMask src1 src2) (MaskAll m1))); + match(Set dst (XorVMask src1 (XorVMask src2 (MaskAll m1)))); + format %{ "vmask_xnorL $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmxnor_mm(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_notI(vRegMask dst, vRegMask src, immI_M1 m1) %{ + match(Set dst (XorVMask src (MaskAll m1))); + format %{ "vmask_notI $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnot_m(as_VectorRegister($dst$$reg), + as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_notL(vRegMask dst, vRegMask src, immL_M1 m1) %{ + match(Set dst (XorVMask src (MaskAll m1))); + format %{ "vmask_notL $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vmnot_m(as_VectorRegister($dst$$reg), + as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + instruct vmask_or(vRegMask dst, vRegMask src1, vRegMask src2) %{ match(Set dst (OrVMask src1 src2)); format %{ "vmask_or $dst, $src1, $src2" %} diff --git a/src/hotspot/cpu/riscv/runtime_riscv.cpp b/src/hotspot/cpu/riscv/runtime_riscv.cpp index 5a1fdbe773a1..62c61bf436a8 100644 --- a/src/hotspot/cpu/riscv/runtime_riscv.cpp +++ b/src/hotspot/cpu/riscv/runtime_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -246,8 +246,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Jump to interpreter __ ret(); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. UncommonTrapBlob* ut_blob = UncommonTrapBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); @@ -389,8 +388,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ jr(t1); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Set exception blob ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index f28230f23bc5..f1bc7fc0d5e3 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -1392,7 +1392,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, assert(vep_offset != -1, "Must be set"); #endif - __ flush(); + // Code will be copied. No ICache sync required. nmethod* nm = nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -1430,7 +1430,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, in_sig_bt, in_regs); int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period - __ flush(); + // Code will be copied. No ICache sync required. int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually return nmethod::new_native_nmethod(method, compile_id, @@ -1817,9 +1817,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, Label safepoint_in_progress, safepoint_in_progress_done; - __ mv(t0, _thread_in_vm); - - __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + // change thread state + __ mv(t1, _thread_in_Java); + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + __ sw(t1, Address(xthread, JavaThread::thread_state_offset())); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -1834,12 +1835,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ bind(safepoint_in_progress_done); } - // change thread state - __ la(t1, Address(xthread, JavaThread::thread_state_offset())); - __ mv(t0, _thread_in_Java); - __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - __ sw(t0, Address(t1)); - if (method->is_object_wait0()) { // Check preemption for Object.wait() __ ld(t1, Address(xthread, JavaThread::preempt_alternate_return_offset())); @@ -2040,7 +2035,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, #ifndef PRODUCT assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); #endif - __ rt_call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); // Restore any method result value restore_native_result(masm, ret_type, stack_slots); @@ -2082,7 +2077,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } } - __ flush(); + // Code will be copied. No ICache sync required. nmethod *nm = nmethod::new_native_nmethod(method, compile_id, @@ -2421,8 +2416,7 @@ void SharedRuntime::generate_deopt_blob() { // Jump to interpreter __ ret(); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); assert(_deopt_blob != nullptr, "create deoptimization blob fail!"); @@ -2567,8 +2561,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ stop("Attempting to adjust pc to skip safepoint poll but the return point is not what we expected"); #endif - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Fill-out other meta info SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); @@ -2663,9 +2656,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ ld(x10, Address(xthread, Thread::pending_exception_offset())); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // return the blob RuntimeStub* rs_blob = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 260d31fc7cdc..7cefb1eef2c9 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -1240,8 +1240,8 @@ class StubGenerator: public StubCodeGenerator { void verify_oop_array(size_t size, Register a, Register count, Register temp) { Label loop, end; __ mv(t1, zr); - __ slli(t0, count, exact_log2(size)); __ bind(loop); + __ slli(t0, count, exact_log2(size)); __ bgeu(t1, t0, end); __ add(temp, a, t1); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index ef23498da5c7..bf552678f965 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1210,11 +1210,9 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ push(ltos); // change thread state - // Force all preceding writes to be observed prior to thread state change + __ mv(t1, _thread_in_Java); __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - - __ mv(t0, _thread_in_vm); - __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); + __ sw(t1, Address(xthread, JavaThread::thread_state_offset())); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -1236,19 +1234,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // hand. // __ mv(c_rarg0, xthread); - __ rt_call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); __ get_method(xmethod); __ reinit_heapbase(); __ bind(Continue); } - // change thread state - // Force all preceding writes to be observed prior to thread state change - __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - - __ mv(t0, _thread_in_Java); - __ sw(t0, Address(xthread, JavaThread::thread_state_offset())); - // Check preemption for Object.wait() Label not_preempted; __ ld(t1, Address(xthread, JavaThread::preempt_alternate_return_offset())); diff --git a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp index 0fccce171bbc..70dafd94fe23 100644 --- a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -330,7 +330,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. #ifndef PRODUCT stringStream ss; diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp index 4fc70e7656f2..73948ef6429d 100644 --- a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp @@ -137,7 +137,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) __ ld(t1, Address(xmethod, entry_offset)); __ jr(t1); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); return s; @@ -246,7 +246,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) assert(SharedRuntime::get_handle_wrong_method_stub() != nullptr, "check initialization order"); __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); return s; diff --git a/src/hotspot/cpu/s390/bytes_s390.hpp b/src/hotspot/cpu/s390/bytes_s390.hpp deleted file mode 100644 index ed6418bd4511..000000000000 --- a/src/hotspot/cpu/s390/bytes_s390.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2022 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_S390_BYTES_S390_HPP -#define CPU_S390_BYTES_S390_HPP - -#include "memory/allStatic.hpp" - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in - // platform-specific byte ordering. - - // Use regular load and store for unaligned access. - // - // On z/Architecture, unaligned loads and stores are supported when using the - // "traditional" load (LH, L/LY, LG) and store (STH, ST/STY, STG) instructions. - // The penalty for unaligned access is just very few (two or three) ticks, - // plus another few (two or three) ticks if the access crosses a cache line boundary. - // - // In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data. - - static inline u2 get_native_u2(address p) { return *(u2*)p; } - static inline u4 get_native_u4(address p) { return *(u4*)p; } - static inline u8 get_native_u8(address p) { return *(u8*)p; } - - static inline void put_native_u2(address p, u2 x) { *(u2*)p = x; } - static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; } - static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; } - - // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) - static inline u2 get_Java_u2(address p) { return get_native_u2(p); } - static inline u4 get_Java_u4(address p) { return get_native_u4(p); } - static inline u8 get_Java_u8(address p) { return get_native_u8(p); } - - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, x); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, x); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, x); } -}; - -#endif // CPU_S390_BYTES_S390_HPP diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index d3c143c97aa8..14e72183e90b 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -3109,13 +3109,8 @@ void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // We are storing into an array that *may* be null-free (the declared type is // Object[], abstract[], interface[] or VT.ref[]). - Label test_mark_word; Register tmp = op->tmp()->as_register(); __ z_lg(tmp, oopDesc::mark_offset_in_bytes(), op->array()->as_register()); - __ z_tmll(tmp, markWord::unlocked_value); - __ z_brnaz(test_mark_word); - __ load_prototype_header(tmp, op->array()->as_register()); - __ bind(test_mark_word); __ z_tmll(tmp, markWord::null_free_array_bit_in_place); } diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp index 4fe4c31567a0..49d7ab0d487e 100644 --- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp +++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp @@ -247,7 +247,8 @@ void DowncallLinker::StubGenerator::generate() { if (_needs_transition) { __ block_comment("thread_native2java {"); - __ set_thread_state(_thread_in_vm); + // change thread state + __ set_thread_state(_thread_in_Java); if (!UseSystemMemoryBarrier) { __ z_fence(); // Order state change wrt. safepoint poll. @@ -260,9 +261,6 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_after_safepoint_poll); - // change thread state - __ set_thread_state(_thread_in_Java); - __ block_comment("reguard_stack_check {"); __ z_cli(Address(Z_thread, JavaThread::stack_guard_state_offset() + in_ByteSize(sizeof(StackOverflow::StackGuardState) - 1)), @@ -288,7 +286,7 @@ void DowncallLinker::StubGenerator::generate() { // Need to save the native result registers around any runtime calls. out_reg_spiller.generate_spill(_masm, out_spill_offset); - __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, JavaThread::check_special_condition_for_native_trans)); + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, SharedRuntime::check_special_condition_for_native_trans)); __ z_lgr(Z_ARG1, Z_thread); __ call(call_target_address); @@ -316,5 +314,5 @@ void DowncallLinker::StubGenerator::generate() { ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. } diff --git a/src/hotspot/cpu/s390/interpreterRT_s390.cpp b/src/hotspot/cpu/s390/interpreterRT_s390.cpp index c9d7adbc36a8..75d8a648a262 100644 --- a/src/hotspot/cpu/s390/interpreterRT_s390.cpp +++ b/src/hotspot/cpu/s390/interpreterRT_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,7 +139,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin iterate(fingerprint); __ load_const_optimized(Z_RET, AbstractInterpreter::result_handler(method()->result_type())); __ z_br(Z_R14); - __ flush(); + __ invalidate_icache(); } #undef __ diff --git a/src/hotspot/cpu/s390/jniFastGetField_s390.cpp b/src/hotspot/cpu/s390/jniFastGetField_s390.cpp index 00c9316c3551..3456afdc674d 100644 --- a/src/hotspot/cpu/s390/jniFastGetField_s390.cpp +++ b/src/hotspot/cpu/s390/jniFastGetField_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,7 +138,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { __ load_const_optimized(Robj, slow_case_addr); __ z_br(Robj); // tail call - __ flush(); + __ invalidate_icache(); return fast_entry; } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index e8971e7630e6..bb4a10a5f80b 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -4236,11 +4236,6 @@ void MacroAssembler::load_metadata(Register dst, Register src) { } } -void MacroAssembler::load_prototype_header(Register dst, Register src) { - load_klass(dst, src); - z_lg(dst, Address(dst, Klass::prototype_header_offset())); -} - void MacroAssembler::store_klass(Register klass, Register dst_oop, Register ck) { assert(!UseCompactObjectHeaders, "Don't use with compact headers"); assert_different_registers(dst_oop, klass, Z_R0); @@ -6377,7 +6372,7 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register temp1 { // Try to lock. Transition lock bits 0b01 => 0b00 const Register locked_obj = top; - z_oill(mark, markWord::unlocked_value); + z_oill(mark, markWord::lock_neutral_value); if (Arguments::is_valhalla_enabled()) { static_assert((uint32_t)markWord::inline_type_bit_in_place <= 0x7FFFFFFF, "inline_type_bit_in_place must fit in low 32 bits for z_nilf"); @@ -6386,7 +6381,7 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register temp1 } z_lgr(locked_obj, mark); // Clear lock-bits from locked_obj (locked state) - z_xilf(locked_obj, markWord::unlocked_value); + z_xilf(locked_obj, markWord::lock_neutral_value); z_csg(mark, locked_obj, mark_offset, obj); branch_optimized(Assembler::bcondNotEqual, slow); } @@ -6458,7 +6453,7 @@ void MacroAssembler::fast_unlock(Register obj, Register temp1, Register temp2, L #ifdef ASSERT // Check header not unlocked (0b01). NearLabel not_unlocked; - z_tmll(mark, markWord::unlocked_value); + z_tmll(mark, markWord::lock_neutral_value); z_braz(not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); @@ -6467,7 +6462,7 @@ void MacroAssembler::fast_unlock(Register obj, Register temp1, Register temp2, L { // Try to unlock. Transition lock bits 0b00 => 0b01 Register unlocked_obj = top; z_lgr(unlocked_obj, mark); - z_oill(unlocked_obj, markWord::unlocked_value); + z_oill(unlocked_obj, markWord::lock_neutral_value); z_csg(mark, unlocked_obj, mark_offset, obj); branch_optimized(Assembler::bcondEqual, unlocked); } @@ -6538,7 +6533,7 @@ void MacroAssembler::compiler_fast_lock_object(Register obj, Register box, Regis { // Try to lock. Transition lock bits 0b01 => 0b00 assert(mark_offset == 0, "required to avoid a lea"); const Register locked_obj = top; - z_oill(mark, markWord::unlocked_value); + z_oill(mark, markWord::lock_neutral_value); if (Arguments::is_valhalla_enabled()) { static_assert((uint32_t)markWord::inline_type_bit_in_place <= 0x7FFFFFFF, "inline_type_bit_in_place must fit in low 32 bits for z_nilf"); @@ -6547,7 +6542,7 @@ void MacroAssembler::compiler_fast_lock_object(Register obj, Register box, Regis } z_lgr(locked_obj, mark); // Clear lock-bits from locked_obj (locked state) - z_xilf(locked_obj, markWord::unlocked_value); + z_xilf(locked_obj, markWord::lock_neutral_value); z_csg(mark, locked_obj, mark_offset, obj); branch_optimized(Assembler::bcondNotEqual, slow_path); } @@ -6725,7 +6720,7 @@ void MacroAssembler::compiler_fast_unlock_object(Register obj, Register box, Reg #ifdef ASSERT // Check header not unlocked (0b01). NearLabel not_unlocked; - z_tmll(mark, markWord::unlocked_value); + z_tmll(mark, markWord::lock_neutral_value); z_braz(not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); @@ -6734,7 +6729,7 @@ void MacroAssembler::compiler_fast_unlock_object(Register obj, Register box, Reg { // Try to unlock. Transition lock bits 0b00 => 0b01 Register unlocked_obj = top; z_lgr(unlocked_obj, mark); - z_oill(unlocked_obj, markWord::unlocked_value); + z_oill(unlocked_obj, markWord::lock_neutral_value); z_csg(mark, unlocked_obj, mark_offset, obj); branch_optimized(Assembler::bcondEqual, unlocked); } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index 3fd182144724..2b831d1a49cf 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -863,7 +863,6 @@ class MacroAssembler: public Assembler { void decode_klass_not_null(Register dst); void load_klass(Register klass, Address mem); void load_klass(Register klass, Register src_oop); - void load_prototype_header(Register dst, Register src); void store_klass(Register klass, Register dst_oop, Register ck = noreg); // Klass will get compressed if ck not provided. void store_klass_gap(Register s, Register dst_oop); void load_narrow_klass_compact(Register dst, Register src); diff --git a/src/hotspot/cpu/s390/runtime_s390.cpp b/src/hotspot/cpu/s390/runtime_s390.cpp index 658fba069b4c..ddfe8afe2a2d 100644 --- a/src/hotspot/cpu/s390/runtime_s390.cpp +++ b/src/hotspot/cpu/s390/runtime_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,8 +142,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ z_br(handle_exception); - // Make sure all code is generated. - masm->flush(); + // Code will be copied. No ICache sync required. // Set exception blob. OopMapSet *oop_maps = nullptr; diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index b6b22102d011..aad194900450 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2024 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * Copyright (c) 2026 IBM Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2220,7 +2220,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, assert(vep_offset != -1, "Must be set"); #endif - __ flush(); + // Code will be copied. No ICache sync required. nmethod* nm = nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -2250,7 +2250,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, int frame_complete = ((intptr_t)__ pc()) - start; // Not complete, period. - __ flush(); + // Code will be copied. No ICache sync required. int stack_slots = SharedRuntime::out_preserve_stack_slots(); // No out slots at all, actually. @@ -2745,8 +2745,13 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, break; } - // Transition from _thread_in_native to _thread_in_vm. - __ set_thread_state(_thread_in_vm); + // Transition from _thread_in_native to _thread_in_Java. + __ set_thread_state(_thread_in_Java); + + // Force this write out before the read below. + if (!UseSystemMemoryBarrier) { + __ z_fence(); + } // Safepoint synchronization //-------------------------------------------------------------------- @@ -2760,11 +2765,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, save_native_result(masm, ret_type, workspace_slot_offset); // Make Z_R2 available as work reg. - // Force this write out before the read below. - if (!UseSystemMemoryBarrier) { - __ z_fence(); - } - __ safepoint_poll(sync, Z_R1); __ load_and_test_int(Z_R0, Address(Z_thread, JavaThread::suspend_flags_offset())); @@ -2776,9 +2776,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // a distinct one for this pc. // __ bind(sync); - __ z_acquire(); - address entry_point = CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans); + address entry_point = CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans); __ call_VM_leaf(entry_point, Z_thread); @@ -2786,13 +2785,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, restore_native_result(masm, ret_type, workspace_slot_offset); } - //-------------------------------------------------------------------- - // Thread state is _thread_in_vm. Any safepoint blocking has - // already happened so we can now change state to _thread_in_Java. - //-------------------------------------------------------------------- - // Transition from _thread_in_vm to _thread_in_Java. - __ set_thread_state(_thread_in_Java); - // Check preemption for Object.wait() if (method->is_object_wait0()) { NearLabel not_preempted; @@ -2968,7 +2960,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ restore_return_pc(); __ z_br(Z_R1_scratch); - __ flush(); + // Code will be copied. No ICache sync required. ////////////////////////////////////////////////////////////////////// // end of code generation ////////////////////////////////////////////////////////////////////// @@ -3543,8 +3535,7 @@ void SharedRuntime::generate_deopt_blob() { // return to the interpreter entry point. __ z_br(Z_R14); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers, SuperwordUseVX)/wordSize); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); @@ -3682,7 +3673,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // return to the interpreter entry point __ z_br(Z_R14); - masm->flush(); + // Code will be copied. No ICache sync required. return UncommonTrapBlob::create(&buffer, nullptr, framesize_in_bytes/wordSize); } #endif // COMPILER2 @@ -3780,8 +3771,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ z_br(Z_R14); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Fill-out other meta info return SafepointBlob::create(&buffer, oop_maps, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers, save_vectors)/wordSize); @@ -3863,8 +3853,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ z_br(Z_R1_scratch); // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // return the blob // frame_size_words or bytes?? diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index c0a1b06954da..ddcba7b25339 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -1575,13 +1575,14 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // In order for GC to work, don't clear the last_Java_sp until after // blocking. - __ set_thread_state(_thread_in_vm); + // Transition from _thread_in_native to _thread_in_Java. + // Force this write out before the read below; + __ set_thread_state(_thread_in_Java); if (!UseSystemMemoryBarrier) { __ z_fence(); } - // Now before we return to java we must look for a current safepoint - // (a new safepoint can not start since we entered _thread_in_vm). + // Now before we return to java we must look for a current safepoint. // We must check here because a current safepoint could be in progress. // Check for safepoint operation in progress and/or pending suspend requests. @@ -1593,17 +1594,13 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ z_bre(Continue); // 0 -> no flag set -> not suspended __ bind(do_safepoint); __ z_lgr(Z_ARG1, Z_thread); - __ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ call_c(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); __ bind(Continue); } //============================================================================= // Back in Interpreter Frame. - // We are in _thread_in_vm here and back in the normal - // interpreter frame. We don't have to do anything special about - // safepoints and we can switch to Java mode anytime we are ready. - // Note: frame::interpreter_frame_result has a dependency on how the // method result is saved across the call to post_method_exit. For // native methods it assumes that the non-FPU/non-void result is @@ -1614,10 +1611,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { //============================================================================= // Back in Java. - // Memory ordering: Z does not reorder store/load with subsequent - // load. That's strong enough. - __ set_thread_state(_thread_in_Java); - __ reset_last_Java_frame(); // We reset the JNI handle block only after unboxing the result; see below. diff --git a/src/hotspot/cpu/s390/upcallLinker_s390.cpp b/src/hotspot/cpu/s390/upcallLinker_s390.cpp index de57e5e0cc49..e940f0df2b93 100644 --- a/src/hotspot/cpu/s390/upcallLinker_s390.cpp +++ b/src/hotspot/cpu/s390/upcallLinker_s390.cpp @@ -271,7 +271,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, ////////////////////////////////////////////////////////////////////////////// - _masm->flush(); + // Code will be copied. No ICache sync required. #ifndef PRODUCT stringStream ss; diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 95ca00d4d1a6..eb0a5a63223e 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2024 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1142,7 +1142,7 @@ void VM_Version::determine_features() { a->z_br(Z_R14); address code_end = a->pc(); - a->flush(); + a->invalidate_icache(); cbuf.insts()->set_end(code_end); diff --git a/src/hotspot/cpu/s390/vtableStubs_s390.cpp b/src/hotspot/cpu/s390/vtableStubs_s390.cpp index de4049ccacfe..596f3bc1c229 100644 --- a/src/hotspot/cpu/s390/vtableStubs_s390.cpp +++ b/src/hotspot/cpu/s390/vtableStubs_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,7 +141,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) __ z_lg(Z_R1_scratch, in_bytes(Method::from_compiled_offset()), Z_method); __ z_br(Z_R1_scratch); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, 0); return s; @@ -235,7 +235,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta); __ z_br(Z_R1_scratch); - masm->flush(); + masm->invalidate_icache(); bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, 0); return s; diff --git a/src/hotspot/cpu/x86/bytes_x86.hpp b/src/hotspot/cpu/x86/bytes_x86.hpp deleted file mode 100644 index 3f7f42342600..000000000000 --- a/src/hotspot/cpu/x86/bytes_x86.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 1997, 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. - * - */ - -#ifndef CPU_X86_BYTES_X86_HPP -#define CPU_X86_BYTES_X86_HPP - -#include "memory/allStatic.hpp" -#include "utilities/align.hpp" -#include "utilities/byteswap.hpp" -#include "utilities/macros.hpp" - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - template - static inline T get_native(const void* p) { - assert(p != nullptr, "null pointer"); - - T x; - - if (is_aligned(p, sizeof(T))) { - x = *(T*)p; - } else { - memcpy(&x, p, sizeof(T)); - } - - return x; - } - - template - static inline void put_native(void* p, T x) { - assert(p != nullptr, "null pointer"); - - if (is_aligned(p, sizeof(T))) { - *(T*)p = x; - } else { - memcpy(p, &x, sizeof(T)); - } - } - - static inline u2 get_native_u2(address p) { return get_native((void*)p); } - static inline u4 get_native_u4(address p) { return get_native((void*)p); } - static inline u8 get_native_u8(address p) { return get_native((void*)p); } - static inline void put_native_u2(address p, u2 x) { put_native((void*)p, x); } - static inline void put_native_u4(address p, u4 x) { put_native((void*)p, x); } - static inline void put_native_u8(address p, u8 x) { put_native((void*)p, x); } - - // Efficient reading and writing of unaligned unsigned data in Java - // byte ordering (i.e. big-endian ordering). Byte-order reversal is - // needed since x86 CPUs use little-endian format. - template - static inline T get_Java(const address p) { - T x = get_native(p); - - if (Endian::is_Java_byte_ordering_different()) { - x = byteswap(x); - } - - return x; - } - - template - static inline void put_Java(address p, T x) { - if (Endian::is_Java_byte_ordering_different()) { - x = byteswap(x); - } - - put_native(p, x); - } - - static inline u2 get_Java_u2(address p) { return get_Java(p); } - static inline u4 get_Java_u4(address p) { return get_Java(p); } - static inline u8 get_Java_u8(address p) { return get_Java(p); } - - static inline void put_Java_u2(address p, u2 x) { put_Java(p, x); } - static inline void put_Java_u4(address p, u4 x) { put_Java(p, x); } - static inline void put_Java_u8(address p, u8 x) { put_Java(p, x); } -}; - -#endif // CPU_X86_BYTES_X86_HPP diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index 84f99215f156..23a457913e5a 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -262,7 +262,6 @@ void LIR_Assembler::osr_entry() { // // build frame - ciMethod* m = compilation()->method(); __ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); // OSR buffer is @@ -1339,7 +1338,6 @@ void LIR_Assembler::type_profile_helper(Register mdo, void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { // we always need a stub for the failure case. - CodeStub* stub = op->stub(); Register obj = op->object()->as_register(); Register k_RInfo = op->tmp1()->as_register(); Register klass_RInfo = op->tmp2()->as_register(); @@ -1577,13 +1575,8 @@ void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // We are storing into an array that *may* be null-free (the declared type is // Object[], abstract[], interface[] or VT.ref[]). - Label test_mark_word; Register tmp = op->tmp()->as_register(); __ movptr(tmp, Address(op->array()->as_register(), oopDesc::mark_offset_in_bytes())); - __ testl(tmp, markWord::unlocked_value); - __ jccb(Assembler::notZero, test_mark_word); - __ load_prototype_header(tmp, op->array()->as_register(), rscratch1); - __ bind(test_mark_word); __ testl(tmp, markWord::null_free_array_bit_in_place); } @@ -2341,7 +2334,7 @@ void LIR_Assembler::emit_static_call_stub() { return; } - int start = __ offset(); + DEBUG_ONLY(int start = __ offset();) // make sure that the displacement word of the call ends up word aligned __ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size_rex + NativeCall::displacement_offset); @@ -2937,7 +2930,6 @@ void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); int bci = op->profiled_bci(); - ciMethod* callee = op->profiled_callee(); Register tmp_load_klass = rscratch1; // Update counter for all call types diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index 95de5906b62a..2642372bc373 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -674,7 +674,7 @@ LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_ } LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) { - bool is_oop = is_reference_type(type); + DEBUG_ONLY(bool is_oop = is_reference_type(type);) LIR_Opr result = new_register(type); value.load_item(); // Because we want a 2-arg form of xchg and xadd @@ -920,7 +920,6 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions support"); // Make all state_for calls early since they can emit code LIR_Opr result = rlock_result(x); - int flags = 0; switch (x->id()) { case vmIntrinsics::_updateCRC32: { LIRItem crc(x->argument_at(0), this); diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index 20b6ee0a15ff..ecb997e878ac 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -814,7 +814,6 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { // for better readability - const bool must_gc_arguments = true; const bool dont_gc_arguments = false; // default value; overwritten for some optimized stubs that are called from methods that do not use the fpu diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 6e08f438a4af..e69a210117ef 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -313,8 +313,8 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register rax_reg, // Try to lock. Transition lock bits 0b01 => 0b00 movptr(rax_reg, mark); - orptr(rax_reg, markWord::unlocked_value); - andptr(mark, ~(int32_t)markWord::unlocked_value); + orptr(rax_reg, markWord::lock_neutral_value); + andptr(mark, ~(int32_t)markWord::lock_neutral_value); lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); jcc(Assembler::notEqual, slow_path); @@ -511,7 +511,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register t, // Try to unlock. Transition lock bits 0b00 => 0b01 movptr(reg_rax, mark); andptr(reg_rax, ~(int32_t)markWord::lock_mask_in_place); - orptr(mark, markWord::unlocked_value); + orptr(mark, markWord::lock_neutral_value); lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); jcc(Assembler::notEqual, push_and_slow_path); jmp(unlocked); @@ -2243,7 +2243,6 @@ void C2_MacroAssembler::reduce16S(int opcode, Register dst, Register src1, XMMRe void C2_MacroAssembler::reduce32S(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2) { assert_different_registers(src2, vtmp1); - int vector_len = Assembler::AVX_256bit; vextracti64x4_high(vtmp1, src2); reduce_operation_256(T_SHORT, opcode, vtmp1, vtmp1, src2); reduce16S(opcode, dst, src1, vtmp1, vtmp1, vtmp2); @@ -2507,7 +2506,6 @@ XMMRegister C2_MacroAssembler::get_lane(BasicType typ, XMMRegister dst, XMMRegis int esize = type2aelembytes(typ); int elem_per_lane = 16/esize; int lane = elemindex / elem_per_lane; - int eindex = elemindex % elem_per_lane; if (lane >= 2) { assert(UseAVX > 2, "required"); @@ -5188,7 +5186,7 @@ void C2_MacroAssembler::vector_castF2X_avx(BasicType to_elem_bt, XMMRegister dst void C2_MacroAssembler::vector_castF2X_evex(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, Register rscratch, int vec_enc) { - int to_elem_sz = type2aelembytes(to_elem_bt); + DEBUG_ONLY(int to_elem_sz = type2aelembytes(to_elem_bt);) assert(to_elem_sz <= 4, ""); vcvttps2dq(dst, src, vec_enc); vector_cast_fp_to_int_special_cases_evex(T_FLOAT, dst, src, xtmp1, xtmp2, ktmp1, ktmp2, rscratch, float_sign_flip, vec_enc); diff --git a/src/hotspot/cpu/x86/c2_init_x86.cpp b/src/hotspot/cpu/x86/c2_init_x86.cpp index 4d8db39bb0c5..0a74d0f7f3ac 100644 --- a/src/hotspot/cpu/x86/c2_init_x86.cpp +++ b/src/hotspot/cpu/x86/c2_init_x86.cpp @@ -36,7 +36,6 @@ void Compile::pd_compiler2_init() { if (UseAVX < 3) { int delta = XMMRegister::max_slots_per_register * XMMRegister::number_of_registers; int bottom = ConcreteRegisterImpl::max_fpr; - int top = bottom + delta; int middle = bottom + (delta / 2); int xmm_slots = XMMRegister::max_slots_per_register; int lower = xmm_slots / 2; diff --git a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp index b71fb46f0758..6585b60f8a0b 100644 --- a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp +++ b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp @@ -220,7 +220,7 @@ static void generate_string_indexof_stubs(StubGenerator *stubgen, address *fnptr assert(StubInfo::entry_count(stub_id) == 1, "sanity check"); GrowableArray

extras; - const int expected_extra_count = 2 * NUMBER_OF_CASES; + DEBUG_ONLY(const int expected_extra_count = 2 * NUMBER_OF_CASES;) address start = stubgen->load_archive_data(stub_id, nullptr, &extras); if (start != nullptr) { assert(extras.length() == expected_extra_count, @@ -1009,7 +1009,6 @@ static void broadcast_first_and_last_needle(Register needle, Register needle_len MacroAssembler *_masm) { bool isUL = (ae == StrIntrinsicNode::UL); bool isUU = (ae == StrIntrinsicNode::UU); - bool isU = (isUU || isUL); Label L_short; // Always need needle broadcast to ymm registers @@ -1776,8 +1775,6 @@ static void setup_jump_tables(StrIntrinsicNode::ArgEncoding ae, Label &L_error, bool isU = isUL || isUU; // At least one is UTF-16 const XMMRegister byte_1 = XMM_BYTE_1; - int jmp_ndx = 0; - //////////////////////////////////////////////// // On entry to each case, the register state is: // diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index 2480e68e7b86..5d6286786683 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -310,7 +310,8 @@ void DowncallLinker::StubGenerator::generate() { __ block_comment("{ thread native2java"); __ restore_cpu_control_state_after_jni(rscratch1); - __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_vm); + // change thread state + __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -325,9 +326,6 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_after_safepoint_poll); - // change thread state - __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java); - __ block_comment("reguard stack check"); __ cmpl(Address(r15_thread, JavaThread::stack_guard_state_offset()), StackOverflow::stack_guard_yellow_reserved_disabled); __ jcc(Assembler::equal, L_reguard); @@ -351,7 +349,7 @@ void DowncallLinker::StubGenerator::generate() { } __ mov(c_rarg0, r15_thread); - runtime_call(_masm, CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + runtime_call(_masm, CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans)); if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, out_spill_rsp_offset); @@ -381,5 +379,5 @@ void DowncallLinker::StubGenerator::generate() { } ////////////////////////////////////////////////////////////////////////////// - __ flush(); + // Code will be copied. No ICache sync required. } diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index 0c640dde285c..af74e29fb6fe 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -34,14 +34,14 @@ source %{ #include "c2_intelJccErratum_x86.hpp" #include "gc/z/zBarrierSetAssembler.hpp" -static void z_color(MacroAssembler* masm, const MachNode* node, Register ref) { +static void z_color(MacroAssembler* masm, Register ref) { __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(ref, barrier_Relocation::unpatched); __ orq_imm32(ref, barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } -static void z_uncolor(MacroAssembler* masm, const MachNode* node, Register ref) { +static void z_uncolor(MacroAssembler* masm, Register ref) { __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shrq(ref, barrier_Relocation::unpatched); } @@ -53,7 +53,7 @@ static void z_keep_alive_load_barrier(MacroAssembler* masm, const MachNode* node ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref); __ jcc(Assembler::notEqual, *stub->entry()); - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); __ bind(*stub->continuation()); } @@ -69,7 +69,7 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r return; } - z_uncolor(masm, node, ref); + z_uncolor(masm, ref); if (node->barrier_data() == ZBarrierElided) { return; } @@ -87,7 +87,7 @@ static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address if (rnew_zaddress != noreg) { // noreg means null; no need to color __ movptr(rnew_zpointer, rnew_zaddress); - z_color(masm, node, rnew_zpointer); + z_color(masm, rnew_zpointer); } } else { bool is_native = (node->barrier_data() & ZBarrierNative) != 0; @@ -200,10 +200,10 @@ instruct zCompareAndExchangeP(indirect mem, no_rax_RegP newval, rRegP tmp, rax_R assert_different_registers($oldval$$Register, $newval$$Register); const Address mem_addr = Address($mem$$Register, 0); z_store_barrier(masm, this, mem_addr, $newval$$Register, $tmp$$Register, true /* is_atomic */); - z_color(masm, this, $oldval$$Register); + z_color(masm, $oldval$$Register); __ lock(); __ cmpxchgptr($tmp$$Register, mem_addr); - z_uncolor(masm, this, $oldval$$Register); + z_uncolor(masm, $oldval$$Register); %} ins_pipe(pipe_cmpxchg); @@ -223,7 +223,7 @@ instruct zCompareAndSwapP(rRegI res, indirect mem, rRegP newval, rRegP tmp, rax_ assert_different_registers($oldval$$Register, $mem$$Register); const Address mem_addr = Address($mem$$Register, 0); z_store_barrier(masm, this, mem_addr, $newval$$Register, $tmp$$Register, true /* is_atomic */); - z_color(masm, this, $oldval$$Register); + z_color(masm, $oldval$$Register); __ lock(); __ cmpxchgptr($tmp$$Register, mem_addr); __ setcc(Assembler::equal, $res$$Register); @@ -245,7 +245,7 @@ instruct zXChgP(indirect mem, rRegP newval, rRegP tmp, rFlagsReg cr) %{ z_store_barrier(masm, this, mem_addr, $newval$$Register, $tmp$$Register, true /* is_atomic */); __ movptr($newval$$Register, $tmp$$Register); __ xchgptr($newval$$Register, mem_addr); - z_uncolor(masm, this, $newval$$Register); + z_uncolor(masm, $newval$$Register); %} ins_pipe(pipe_cmpxchg); diff --git a/src/hotspot/cpu/x86/icache_x86.hpp b/src/hotspot/cpu/x86/icache_x86.hpp index 92e4fbf15690..a8bdf7f0ec6a 100644 --- a/src/hotspot/cpu/x86/icache_x86.hpp +++ b/src/hotspot/cpu/x86/icache_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,16 +28,6 @@ // Interface for updating the instruction cache. Whenever the VM modifies // code, part of the processor instruction cache potentially has to be flushed. -// On the x86, this is a no-op -- the I-cache is guaranteed to be consistent -// after the next jump, and the VM never modifies instructions directly ahead -// of the instruction fetch path. - -// [phh] It's not clear that the above comment is correct, because on an MP -// system where the dcaches are not snooped, only the thread doing the invalidate -// will see the update. Even in the snooped case, a memory fence would be -// necessary if stores weren't ordered. Fortunately, they are on all known -// x86 implementations. - class ICache : public AbstractICache { public: enum { diff --git a/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp b/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp index 8909df5b3f08..31b074c552be 100644 --- a/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp +++ b/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -295,7 +295,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin __ lea(rax, ExternalAddress(Interpreter::result_handler(method()->result_type()))); __ ret(0); - __ flush(); + __ invalidate_icache(); } diff --git a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp index 2c4d34c7cd54..caa167357f16 100644 --- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { // tail call __ jump (RuntimeAddress(slow_case_addr), rscratch1); - __ flush (); + __ invalidate_icache(); return fast_entry; } @@ -208,7 +208,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { // tail call __ jump (RuntimeAddress(slow_case_addr), rscratch1); - __ flush (); + __ invalidate_icache(); return fast_entry; } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index dd6a6ed51ed4..20ca09968b89 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -5582,11 +5582,6 @@ void MacroAssembler::load_klass(Register dst, Register src, Register tmp) { decode_klass_not_null(dst, tmp); } -void MacroAssembler::load_prototype_header(Register dst, Register src, Register tmp) { - load_klass(dst, src, tmp); - movptr(dst, Address(dst, Klass::prototype_header_offset())); -} - void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { assert(!UseCompactObjectHeaders, "not with compact headers"); assert_different_registers(src, tmp); @@ -10626,8 +10621,8 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register reg_r // Try to lock. Transition lock bits 0b01 => 0b00 movptr(tmp, reg_rax); - andptr(tmp, ~(int32_t)markWord::unlocked_value); - orptr(reg_rax, markWord::unlocked_value); + andptr(tmp, ~(int32_t)markWord::lock_neutral_value); + orptr(reg_rax, markWord::lock_neutral_value); if (Arguments::is_valhalla_enabled()) { // Mask inline_type bit such that we go to the slow path if object is an inline type andptr(reg_rax, ~((int) markWord::inline_type_bit_in_place)); @@ -10682,7 +10677,7 @@ void MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register tmp, L #ifdef ASSERT // Check header not unlocked (0b01). Label not_unlocked; - testptr(reg_rax, markWord::unlocked_value); + testptr(reg_rax, markWord::lock_neutral_value); jcc(Assembler::zero, not_unlocked); stop("fast_unlock already unlocked"); bind(not_unlocked); @@ -10690,7 +10685,7 @@ void MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register tmp, L // Try to unlock. Transition lock bits 0b00 => 0b01 movptr(tmp, reg_rax); - orptr(tmp, markWord::unlocked_value); + orptr(tmp, markWord::lock_neutral_value); lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes())); jcc(Assembler::equal, unlocked); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 7f424966468e..b7c6b379c022 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -407,8 +407,6 @@ class MacroAssembler: public Assembler { // stored using routines that take a jobject. void store_heap_oop_null(Address dst); - void load_prototype_header(Register dst, Register src, Register tmp); - void store_klass_gap(Register dst, Register src); // This dummy is to prevent a call to store_heap_oop from diff --git a/src/hotspot/cpu/x86/runtime_x86_64.cpp b/src/hotspot/cpu/x86/runtime_x86_64.cpp index 5bf65299a0c5..cfd4e8e9df0c 100644 --- a/src/hotspot/cpu/x86/runtime_x86_64.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,8 +231,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Jump to interpreter __ ret(0); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); @@ -370,8 +369,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ jmp(r8); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Set exception blob ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 8d257565c939..0eb629f6ee8e 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -2021,7 +2021,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, assert(vep_offset != -1, "Must be set"); #endif - __ flush(); + // Code will be copied. No ICache sync required. nmethod* nm = nmethod::new_native_nmethod(method, compile_id, masm->code(), @@ -2050,7 +2050,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, in_sig_bt, in_regs); int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period - __ flush(); + // Code will be copied. No ICache sync required. int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually return nmethod::new_native_nmethod(method, compile_id, @@ -2456,7 +2456,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, default : ShouldNotReachHere(); } - __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_vm); + // change thread state + __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -2488,7 +2489,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ mov(r12, rsp); // remember sp __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows __ andptr(rsp, -16); // align stack as required by ABI - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans))); __ mov(rsp, r12); // restore sp __ reinit_heapbase(); // Restore any method result value @@ -2496,9 +2497,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ bind(Continue); } - // change thread state - __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java); - if (method->is_object_wait0()) { // Check preemption for Object.wait() __ movptr(rscratch1, Address(r15_thread, JavaThread::preempt_alternate_return_offset())); @@ -2712,7 +2710,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - __ flush(); + // Code will be copied. No ICache sync required. nmethod *nm = nmethod::new_native_nmethod(method, compile_id, @@ -3064,8 +3062,7 @@ void SharedRuntime::generate_deopt_blob() { // Jump to interpreter __ ret(0); - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); @@ -3248,8 +3245,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) __ stop("Attempting to adjust pc to skip safepoint poll but the return point is not what we expected"); #endif - // Make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // Fill-out other meta info SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); @@ -3340,9 +3336,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. // return the blob // frame_size_words or bytes?? @@ -3864,7 +3858,7 @@ BufferedInlineTypeBlob* SharedRuntime::generate_buffered_inline_type_adapter(con __ bind(skip); __ ret(0); - __ flush(); + // Code will be copied. No ICache sync required. return BufferedInlineTypeBlob::create(&buffer, pack_fields_off, pack_fields_jobject_off, unpack_fields_off); } @@ -4021,9 +4015,7 @@ RuntimeStub* SharedRuntime::generate_return_value_stub(address destination) { __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - // ------------- - // make sure all code is generated - masm->flush(); + // Code will be copied. No ICache sync required. RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, false); AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index 631d23801d33..38dfe1e171b0 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -955,8 +955,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ push(ltos); // change thread state - __ movl(Address(thread, JavaThread::thread_state_offset()), - _thread_in_vm); + __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); // Force this write out before the read below if (!UseSystemMemoryBarrier) { @@ -987,15 +986,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM) __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows __ andptr(rsp, -16); // align stack as required by ABI - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::check_special_condition_for_native_trans))); __ mov(rsp, r12); // restore sp __ reinit_heapbase(); __ bind(Continue); } - // change thread state - __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); - // Check preemption for Object.wait() Label not_preempted; __ movptr(rscratch1, Address(r15_thread, JavaThread::preempt_alternate_return_offset())); diff --git a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp index edc83fa7c562..eb5cda566060 100644 --- a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -351,7 +351,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, __ lea(c_rarg0, Address(rsp, frame_data_offset)); // stack already aligned __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, UpcallLinker::on_exit))); - __ reinit_heapbase(); + assert(!UseCompressedOops || !abi.is_volatile_reg(r12_heapbase), "r12_heapbase is not a volatile_reg!"); __ block_comment("} on_exit"); restore_callee_saved_registers(_masm, abi, reg_save_area_offset); @@ -363,7 +363,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature, ////////////////////////////////////////////////////////////////////////////// - _masm->flush(); + // Code will be copied. No ICache sync required. #ifndef PRODUCT stringStream ss; diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 12cdadf026b6..61b012e74351 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1576,12 +1576,18 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { FLAG_SET_DEFAULT(UseUnalignedLoadStores, true); } + } + #ifdef COMPILER2 + // Enable UseFPUForSpilling on Zen1/Zen2 (family 0x17) and Hygon Dhyana (family 0x18). + // On Zen3 (family 0x19) and beyond it should be default off. + if (cpu_family() >= 0x17 && cpu_family() < 0x19) { if (supports_sse4_2() && FLAG_IS_DEFAULT(UseFPUForSpilling)) { FLAG_SET_DEFAULT(UseFPUForSpilling, true); } -#endif } +#endif // COMPILER2 + } if (is_intel()) { // Intel cpus specific settings diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp index 81929e78d585..f47d1ad2ad5b 100644 --- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp +++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,7 +131,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index, bool caller_is_c1) address ame_addr = __ pc(); __ jmp( Address(rbx, entry_offset)); - masm->flush(); + masm->invalidate_icache(); slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, index_dependent_slop); @@ -248,7 +248,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) // dirty work. __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); - masm->flush(); + masm->invalidate_icache(); slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, index_dependent_slop); diff --git a/src/hotspot/cpu/zero/bytes_zero.hpp b/src/hotspot/cpu/zero/bytes_zero.hpp deleted file mode 100644 index 15d0fc32650f..000000000000 --- a/src/hotspot/cpu/zero/bytes_zero.hpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_ZERO_BYTES_ZERO_HPP -#define CPU_ZERO_BYTES_ZERO_HPP - -#include "memory/allStatic.hpp" - -typedef union unaligned { - u4 u; - u2 us; - u8 ul; -} __attribute__((packed)) unaligned; - -class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in - // platform-specific byte ordering. - static inline u2 get_native_u2(address p){ - unaligned *up = (unaligned *) p; - return up->us; - } - - static inline u4 get_native_u4(address p) { - unaligned *up = (unaligned *) p; - return up->u; - } - - static inline u8 get_native_u8(address p) { - unaligned *up = (unaligned *) p; - return up->ul; - } - - static inline void put_native_u2(address p, u2 x) { - unaligned *up = (unaligned *) p; - up->us = x; - } - - static inline void put_native_u4(address p, u4 x) { - unaligned *up = (unaligned *) p; - up->u = x; - } - - static inline void put_native_u8(address p, u8 x) { - unaligned *up = (unaligned *) p; - up->ul = x; - } - - // Efficient reading and writing of unaligned unsigned data in Java - // byte ordering (i.e. big-endian ordering). -#ifdef VM_LITTLE_ENDIAN - // Byte-order reversal is needed - static inline u2 get_Java_u2(address p) { - return (u2(p[0]) << 8) | - (u2(p[1]) ); - } - static inline u4 get_Java_u4(address p) { - return (u4(p[0]) << 24) | - (u4(p[1]) << 16) | - (u4(p[2]) << 8) | - (u4(p[3]) ); - } - static inline u8 get_Java_u8(address p) { - u4 hi, lo; - hi = (u4(p[0]) << 24) | - (u4(p[1]) << 16) | - (u4(p[2]) << 8) | - (u4(p[3]) ); - lo = (u4(p[4]) << 24) | - (u4(p[5]) << 16) | - (u4(p[6]) << 8) | - (u4(p[7]) ); - return u8(lo) | (u8(hi) << 32); - } - - static inline void put_Java_u2(address p, u2 x) { - p[0] = x >> 8; - p[1] = x; - } - static inline void put_Java_u4(address p, u4 x) { - p[0] = x >> 24; - p[1] = x >> 16; - p[2] = x >> 8; - p[3] = x; - } - static inline void put_Java_u8(address p, u8 x) { - u4 hi, lo; - lo = x; - hi = x >> 32; - p[0] = hi >> 24; - p[1] = hi >> 16; - p[2] = hi >> 8; - p[3] = hi; - p[4] = lo >> 24; - p[5] = lo >> 16; - p[6] = lo >> 8; - p[7] = lo; - } -#else - // No byte-order reversal is needed - static inline u2 get_Java_u2(address p) { - return get_native_u2(p); - } - static inline u4 get_Java_u4(address p) { - return get_native_u4(p); - } - static inline u8 get_Java_u8(address p) { - return get_native_u8(p); - } - - static inline void put_Java_u2(address p, u2 x) { - put_native_u2(p, x); - } - static inline void put_Java_u4(address p, u4 x) { - put_native_u4(p, x); - } - static inline void put_Java_u8(address p, u8 x) { - put_native_u8(p, x); - } -#endif // VM_LITTLE_ENDIAN -}; - -#endif // CPU_ZERO_BYTES_ZERO_HPP diff --git a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp index 89a021ddb294..cc2f5ff0f2e2 100644 --- a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp +++ b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp @@ -41,6 +41,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/sharedRuntime.hpp" #include "runtime/timer.hpp" #include "runtime/timerTrace.hpp" #include "utilities/debug.hpp" @@ -427,18 +428,16 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // ThreadStateTransition::transition_from_native() cannot be used // here because it does not check for asynchronous exceptions. // We have to manage the transition ourself. - thread->set_thread_state_fence(_thread_in_vm); + thread->set_thread_state_fence(_thread_in_Java); // Handle safepoint operations, pending suspend requests, // and pending asynchronous exceptions. if (SafepointMechanism::should_process(thread) || thread->has_special_condition_for_native_trans()) { - JavaThread::check_special_condition_for_native_trans(thread); + SharedRuntime::check_special_condition_for_native_trans(thread); CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops()); } - // Finally we can change the thread state to _thread_in_Java. - thread->set_thread_state(_thread_in_Java); fixup_after_potential_safepoint(); // Notify the stack watermarks machinery that we are unwinding. diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index 1c183a9bbab5..18c1c1eb26f7 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -670,7 +670,7 @@ bool CgroupSubsystem::active_processor_count(int (*cpu_bound_func)(), double& va * * return: * false if retrieving the value failed - * true if retrieving the value was successfull and the value was + * true if retrieving the value was successful and the value was * set in the 'value' reference. */ bool CgroupSubsystem::memory_limit_in_bytes(physical_memory_size_type upper_bound, diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 3ab81697280a..5c84669776db 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -389,7 +389,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp index 6f31bc284e35..90a61b7e8b63 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp @@ -374,7 +374,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 8668f20e371d..a380c4f316cf 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -433,7 +433,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index a089d5981ca5..c9a537feacb5 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -145,14 +145,6 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, ShouldNotCallThis(); } - // jni_fast_GetField can trap at certain pc's if a GC - // kicks in and the heap gets shrunk before the field access. - /*if (sig == SIGSEGV || sig == SIGBUS) { - address addr = JNI_FastGetField::find_slowcase_pc(pc); - if (addr != (address)-1) { - stub = addr; - } - }*/ } return false; diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index 67e0569bf31d..216e6b729909 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -302,7 +302,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 41a4dbea3842..3f158ad9cee4 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -376,7 +376,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if (sig == SIGSEGV || sig == SIGBUS) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 518519937306..859adcd8b4ee 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -405,7 +405,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp index 7634ac0fd379..d059046c57fb 100644 --- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp @@ -283,7 +283,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr_slow = JNI_FastGetField::find_slowcase_pc(pc); if (addr_slow != (address)-1) { stub = addr_slow; diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index 9276d1d744b0..cbb06d2d07d8 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -349,7 +349,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 25ee449d8b10..261739d8c35f 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -297,7 +297,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // jni_fast_GetField can trap at certain pc's if a GC kicks in // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { + if (stub == nullptr && ((sig == SIGSEGV) || (sig == SIGBUS))) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index ee9c5e2dfb23..6cad3e9fff95 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -260,14 +260,6 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, ShouldNotCallThis(); } - // jni_fast_GetField can trap at certain pc's if a GC - // kicks in and the heap gets shrunk before the field access. - /*if (sig == SIGSEGV || sig == SIGBUS) { - address addr = JNI_FastGetField::find_slowcase_pc(pc); - if (addr != (address)-1) { - stub = addr; - } - }*/ } return false; // Fatal error diff --git a/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp index 9238043f7a41..a92e000950fc 100644 --- a/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp @@ -29,12 +29,6 @@ #include #include -// As per atomicAccess.hpp all read-modify-write operations have to provide two-way -// barriers semantics. The memory_order parameter is ignored - we always provide -// the strongest/most-conservative ordering -// -// For AARCH64 we add explicit barriers in the stubs. - template struct AtomicAccess::PlatformAdd { template @@ -56,9 +50,26 @@ struct AtomicAccess::PlatformAdd { I add_value, \ atomic_memory_order order) const { \ STATIC_ASSERT(sizeof(IntrinsicType) == sizeof(D)); \ - return PrimitiveConversions::cast( \ - IntrinsicName(reinterpret_cast(dest), \ - PrimitiveConversions::cast(add_value))); \ + IntrinsicType volatile* d = \ + reinterpret_cast(dest); \ + IntrinsicType inc = \ + PrimitiveConversions::cast(add_value); \ + IntrinsicType result; \ + switch (order) { \ + case memory_order_relaxed: \ + result = _##IntrinsicName##_nf(d, inc); break; \ + case memory_order_acquire: \ + result = _##IntrinsicName##_acq(d, inc); break; \ + case memory_order_release: \ + result = _##IntrinsicName##_rel(d, inc); break; \ + case memory_order_conservative: \ + result = _##IntrinsicName(d, inc); \ + OrderAccess::fence(); \ + break; \ + default: \ + result = _##IntrinsicName(d, inc); break; \ + } \ + return PrimitiveConversions::cast(result); \ } DEFINE_INTRINSIC_ADD(InterlockedAdd, long) @@ -78,9 +89,26 @@ struct AtomicAccess::PlatformXchg<1> : AtomicAccess::XchgUsingCmpxchg<1> {}; STATIC_ASSERT(sizeof(IntrinsicType) == sizeof(T)); \ STATIC_ASSERT(sizeof(IntrinsicType) == 4 || \ sizeof(IntrinsicType) == 8); \ - return PrimitiveConversions::cast( \ - IntrinsicName(reinterpret_cast(dest), \ - PrimitiveConversions::cast(exchange_value))); \ + IntrinsicType volatile* d = \ + reinterpret_cast(dest); \ + IntrinsicType xchg = \ + PrimitiveConversions::cast(exchange_value); \ + IntrinsicType result; \ + switch (order) { \ + case memory_order_relaxed: \ + result = _##IntrinsicName##_nf(d, xchg); break; \ + case memory_order_acquire: \ + result = _##IntrinsicName##_acq(d, xchg); break; \ + case memory_order_release: \ + result = _##IntrinsicName##_rel(d, xchg); break; \ + case memory_order_conservative: \ + result = _##IntrinsicName(d, xchg); \ + OrderAccess::fence(); \ + break; \ + default: \ + result = _##IntrinsicName(d, xchg); break; \ + } \ + return PrimitiveConversions::cast(result); \ } DEFINE_INTRINSIC_XCHG(InterlockedExchange, long) @@ -90,7 +118,9 @@ DEFINE_INTRINSIC_XCHG(InterlockedExchange64, __int64) // Note: the order of the parameters is different between // AtomicAccess::PlatformCmpxchg<*>::operator() and the -// InterlockedCompareExchange* API. +// _InterlockedCompareExchange* intrinsics: +// HotSpot: (dest, compare_value, exchange_value) +// MSVC: (dest, exchange_value, compare_value) #define DEFINE_INTRINSIC_CMPXCHG(IntrinsicName, IntrinsicType) \ template<> \ @@ -100,16 +130,78 @@ DEFINE_INTRINSIC_XCHG(InterlockedExchange64, __int64) T exchange_value, \ atomic_memory_order order) const { \ STATIC_ASSERT(sizeof(IntrinsicType) == sizeof(T)); \ - return PrimitiveConversions::cast( \ - IntrinsicName(reinterpret_cast(dest), \ - PrimitiveConversions::cast(exchange_value), \ - PrimitiveConversions::cast(compare_value))); \ + IntrinsicType volatile* d = \ + reinterpret_cast(dest); \ + IntrinsicType xchg = \ + PrimitiveConversions::cast(exchange_value); \ + IntrinsicType cmp = \ + PrimitiveConversions::cast(compare_value); \ + IntrinsicType result; \ + switch (order) { \ + case memory_order_relaxed: \ + result = _##IntrinsicName##_nf(d, xchg, cmp); break; \ + case memory_order_acquire: \ + result = _##IntrinsicName##_acq(d, xchg, cmp); break; \ + case memory_order_release: \ + result = _##IntrinsicName##_rel(d, xchg, cmp); break; \ + case memory_order_conservative: \ + result = _##IntrinsicName(d, xchg, cmp); \ + OrderAccess::fence(); \ + break; \ + default: \ + result = _##IntrinsicName(d, xchg, cmp); break; \ + } \ + return PrimitiveConversions::cast(result); \ } -DEFINE_INTRINSIC_CMPXCHG(_InterlockedCompareExchange8, char) // Use the intrinsic as InterlockedCompareExchange8 does not exist +DEFINE_INTRINSIC_CMPXCHG(InterlockedCompareExchange8, char) // Use the intrinsic as InterlockedCompareExchange8 does not exist DEFINE_INTRINSIC_CMPXCHG(InterlockedCompareExchange, long) DEFINE_INTRINSIC_CMPXCHG(InterlockedCompareExchange64, __int64) #undef DEFINE_INTRINSIC_CMPXCHG +#define DEFINE_ORDERED_LOAD(Size, Name, Type) \ + template<> \ + struct AtomicAccess::PlatformOrderedLoad { \ + template \ + T operator()(const volatile T* p) const { \ + T* noconst_ptr = const_cast(p); \ + unsigned Type value = Name(reinterpret_cast(noconst_ptr)); \ + return PrimitiveConversions::cast(value); \ + } \ + }; + +DEFINE_ORDERED_LOAD(1, __ldar8, __int8) +DEFINE_ORDERED_LOAD(2, __ldar16, __int16) +DEFINE_ORDERED_LOAD(4, __ldar32, __int32) +DEFINE_ORDERED_LOAD(8, __ldar64, __int64) + +#undef DEFINE_ORDERED_LOAD + +#define DEFINE_ORDERED_STORE(Size, Name, Type) \ + template<> \ + struct AtomicAccess::PlatformOrderedStore { \ + template \ + void operator()(volatile T* p, T v) const { \ + Name(reinterpret_cast(p), PrimitiveConversions::cast(v)); \ + } \ + }; + +DEFINE_ORDERED_STORE(1, __stlr8, __int8) +DEFINE_ORDERED_STORE(2, __stlr16, __int16) +DEFINE_ORDERED_STORE(4, __stlr32, __int32) +DEFINE_ORDERED_STORE(8, __stlr64, __int64) + +#undef DEFINE_ORDERED_STORE + +template +struct AtomicAccess::PlatformOrderedStore +{ + template + void operator()(volatile T* p, T v) const { + PlatformOrderedStore()(p, v); + OrderAccess::fence(); + } +}; + #endif // OS_CPU_WINDOWS_AARCH64_ATOMICACCESS_WINDOWS_AARCH64_HPP diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index e3291d3a6ca9..31ce1b41f39d 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,7 @@ bool os::win32::register_code_area(char *low, char *high) { pDCD = (pDynamicCodeData) masm->pc(); masm->jump(RuntimeAddress((address)&HandleExceptionFromCodeCache), rscratch1); - masm->flush(); + masm->invalidate_icache(); // Create an Unwind Structure specifying no unwind info // other than an Exception Handler diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 8abaa62982bb..167f19a8fde7 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -3905,15 +3905,14 @@ void MatchNode::count_commutative_op(int& count) { "MaxI","MinI","MaxHF","MinHF","MaxF","MinF","MaxD","MinD", "MulI","MulL","MulHF","MulF","MulD", "OrI","OrL", - "XorI","XorL" - "UMax","UMin" + "XorI","XorL", }; static const char *commut_vector_op_list[] = { "AddVB", "AddVS", "AddVI", "AddVL", "AddVHF", "AddVF", "AddVD", "MulVB", "MulVS", "MulVI", "MulVL", "MulVHF", "MulVF", "MulVD", "AndV", "OrV", "XorV", "AndVMask", "OrVMask", "XorVMask", - "MaxVHF", "MinVHF", "MaxV", "MinV", "UMax","UMin" + "MaxVHF", "MinVHF", "MaxV", "MinV", "UMaxV", "UMinV", }; if (_lChild && _rChild && (_lChild->_lChild || _rChild->_lChild)) { diff --git a/src/hotspot/share/asm/assembler.cpp b/src/hotspot/share/asm/assembler.cpp index 9e342d23afd8..5de8a6dfb10b 100644 --- a/src/hotspot/share/asm/assembler.cpp +++ b/src/hotspot/share/asm/assembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,7 +104,7 @@ void AbstractAssembler::end_a_const(CodeSection* cs) { set_code_section(cs); } -void AbstractAssembler::flush() { +void AbstractAssembler::invalidate_icache() { ICache::invalidate_range(addr_at(0), offset()); } diff --git a/src/hotspot/share/asm/assembler.hpp b/src/hotspot/share/asm/assembler.hpp index bfe785fb94e9..b24e65e12621 100644 --- a/src/hotspot/share/asm/assembler.hpp +++ b/src/hotspot/share/asm/assembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -311,8 +311,8 @@ class AbstractAssembler : public ResourceObj { // Creation AbstractAssembler(CodeBuffer* code); - // ensure buf contains all code (call this before using/copying the code) - void flush(); + // Invalidate ICache after writing code to its final location. + void invalidate_icache(); void emit_int8( int x1) { code_section()->emit_int8(narrow_cast(x1)); } diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index d56ab27f0253..549b2cb20639 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -28,11 +28,11 @@ #include "code/oopRecorder.hpp" #include "code/relocInfo.hpp" #include "compiler/compiler_globals.hpp" +#include "nmt/memTag.hpp" #include "runtime/os.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/growableArray.hpp" -#include "utilities/linkedlist.hpp" #include "utilities/macros.hpp" #include "utilities/resizableHashTable.hpp" @@ -546,7 +546,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { SECT_LIMIT, SECT_NONE = -1 }; - typedef LinkedListImpl Offsets; + typedef GrowableArrayCHeap Offsets; typedef ResizeableHashTable SharedTrampolineRequests; private: diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index 9779b3330b9a..605d3e4c353b 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -258,7 +258,10 @@ class Compilation: public StackObj { } bool profile_array_accesses() { return env()->comp_level() == CompLevel_full_profile && - C1UpdateMethodData; + C1UpdateMethodData && MethodData::profile_array_accesses(); + } + bool profile_acmp() { + return is_profiling() && profile_branches() && MethodData::profile_acmp(); } // will compilation make optimistic assumptions that might lead to diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 115751b129a1..a60a7619f208 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1390,7 +1390,7 @@ void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* sta } } if ((stream()->cur_bc() == Bytecodes::_if_acmpeq || stream()->cur_bc() == Bytecodes::_if_acmpne) && - is_profiling() && profile_branches()) { + profile_acmp()) { compilation()->set_would_profile(true); append(new ProfileACmpTypes(method(), bci(), x, y)); } diff --git a/src/hotspot/share/c1/c1_GraphBuilder.hpp b/src/hotspot/share/c1/c1_GraphBuilder.hpp index 2a8517905013..5fcde20964ba 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.hpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.hpp @@ -430,6 +430,7 @@ class GraphBuilder { bool profile_arguments() { return _compilation->profile_arguments(); } bool profile_return() { return _compilation->profile_return(); } bool profile_array_accesses(){ return _compilation->profile_array_accesses();} + bool profile_acmp() { return _compilation->profile_acmp(); } Values* args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver); Values* collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 19b4d9ae203c..f61daa556699 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1964,7 +1964,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { } } - if (GenerateArrayStoreCheck && needs_store_check) { + if (needs_store_check) { CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci()); } @@ -3097,7 +3097,6 @@ void LIRGenerator::do_Base(Base* x) { __ std_entry(LIR_OprFact::illegalOpr); // Emit moves from physical registers / stack slots to virtual registers CallingConvention* args = compilation()->frame_map()->incoming_arguments(); - IRScope* irScope = compilation()->hir()->top_scope(); int java_index = 0; for (int i = 0; i < args->length(); i++) { LIR_Opr src = args->at(i); @@ -3445,7 +3444,7 @@ void LIRGenerator::do_RuntimeCall(address routine, Intrinsic* x) { assert(x->number_of_arguments() == 0, "wrong type"); // Enforce computation of _reserved_argument_area_size which is required on some platforms. BasicTypeList signature; - CallingConvention* cc = frame_map()->c_calling_convention(&signature); + frame_map()->c_calling_convention(&signature); LIR_Opr reg = result_register_for(x->type()); __ call_runtime_leaf(routine, getThreadTemp(), reg, new LIR_OprList()); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index 70dbad6d91ba..3cb30eab55db 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -744,7 +744,9 @@ void LinearScan::compute_global_live_sets() { // Perform a backward dataflow analysis to compute live_out and live_in for each block. // The loop is executed until a fixpoint is reached (no changes in an iteration) // Exception handlers must be processed because not all live values are - // present in the state array, e.g. because of global value numbering + // present in the state array, e.g. because of global value numbering. + // Exception handler live_in information is also used by build_intervals() to + // account for local liveness holes in exception-throwing blocks. do { change_occurred = false; @@ -1363,6 +1365,55 @@ void LinearScan::build_intervals() { add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr)); } + // If the visited operation 'op' may branch into an exception handler + // block 'handler', add all live-in registers of 'handler' as virtual uses + // of 'op'. This ensures that all such registers are live into 'op', which + // might otherwise not happen if 'op' is scheduled within a hole of their + // corresponding intervals, as in the following + // post-compute_global_live_sets() scenario: + // + // R + // | block: + // | live-in: {.., R, ..} + // | .. + // - kill R + // .. + // op: branch [BE] .. // may branch into 'handler' + // .. + // - def R + // | .. + // | branch into 'block' + // | live-out: {.., R, ..} + // | + // | handler: + // | live-in: {.., R, ..} + // | .. + // + // Normally, the debug information generation logic below will add + // registers such as R in the above scenario as uses of 'op', but this + // might not happen if the corresponding virtual register used within + // 'handler' is replaced by another one in an earlier optimization pass. + // An example of such a replacement is GraphBuilder::shift_op(). + if (compilation()->has_exception_handlers() && op_id != -1 && has_info(op_id)) { + XHandlers* xhandlers = visitor.all_xhandler(); + for (int k = 0; k < xhandlers->length(); k++) { + BlockBegin* handler = xhandlers->handler_at(k)->entry_block(); + auto add_virtual_use_to_op = [&](BitMap::idx_t index) { + int reg = static_cast(index); + // The T_ILLEGAL type is used by add_use() as a sentinel value + // indicating the type is unknown (rather than illegal) so that the + // type of the interval corresponding to reg is not updated. The use + // is extended beyond 'op' (to = op_id + 1) so that liveness is + // preserved across possible registers killed by 'op' (e.g. + // caller-saved registers if 'op' is a call). + TRACE_LINEAR_SCAN(2, tty->print_cr(" use [R%d] from %d to %d (%d)", + reg, block_from, op_id + 1, noUse)); + add_use(reg, block_from, op_id + 1, noUse, T_ILLEGAL); + }; + handler->live_in().iterate(add_virtual_use_to_op); + } + } + // Add uses of live locals from interpreter's point of view for proper // debug information generation // Treat these operands as temp values (if the life range is extended diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index 1adf99cce61e..860a8c5470f3 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,7 +124,6 @@ void RangeCheckEliminator::Visitor::do_LogicOp(LogicOp *lo) { void RangeCheckEliminator::Visitor::do_Phi(Phi *phi) { if (!phi->type()->as_IntType() && !phi->type()->as_ObjectType()) return; - BlockBegin *block = phi->block(); int op_count = phi->operand_count(); bool has_upper = true; bool has_lower = true; @@ -220,7 +219,6 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) { if (ao->op() == Bytecodes::_irem) { Bound* x_bound = _rce->get_bound(x); - Bound* y_bound = _rce->get_bound(y); if (x_bound->lower() >= 0 && x_bound->lower_instr() == nullptr && y->as_ArrayLength() != nullptr) { _bound = new Bound(0, nullptr, -1, y); } else if (x_bound->has_lower() && x_bound->lower() >= 0 && y->type()->as_IntConstant() && @@ -872,7 +870,6 @@ void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, Block } // Lower instruction - Value index_instr = ai->index(); Value lower_instr = index_bound->lower_instr(); if (!loop_invariant(loop_header, lower_instr)) { TRACE_RANGE_CHECK_ELIMINATION( diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 118758f3ea49..d4b1f3a111e7 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -236,8 +236,8 @@ CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, StubId id, const char // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) sasm->align(BytesPerWord); - // make sure all code is in code buffer - sasm->flush(); + + // Code will be copied. No ICache sync required. frame_size = sasm->frame_size(); must_gc_arguments = sasm->must_gc_arguments(); diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index fad45f747b22..e69883bc436d 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,9 +238,6 @@ develop(bool, UseSlowPath, false, \ "For debugging: test slow cases by always using them") \ \ - develop(bool, GenerateArrayStoreCheck, true, \ - "Generates code for array store checks") \ - \ develop(bool, PrintBailouts, false, \ "Print bailout and its reason") \ \ diff --git a/src/hotspot/share/cds/aotClassLocation.cpp b/src/hotspot/share/cds/aotClassLocation.cpp index 48b91960ce77..e33d4b6ff24e 100644 --- a/src/hotspot/share/cds/aotClassLocation.cpp +++ b/src/hotspot/share/cds/aotClassLocation.cpp @@ -39,8 +39,10 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "oops/array.hpp" +#include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "runtime/arguments.hpp" +#include "runtime/handles.inline.hpp" #include "utilities/classpathStream.hpp" #include "utilities/formatBuffer.hpp" #include "utilities/stringUtils.hpp" @@ -279,7 +281,8 @@ AOTClassLocation* AOTClassLocation::allocate(JavaThread* current, const char* pa } assert(*(cs->manifest() + cs->manifest_length()) == '\0', "should be nul-terminated"); - if (strstr(cs->manifest(), "Multi-Release: true") != nullptr) { + const char* multi_release = cs->get_attr("Multi-Release: "); + if (multi_release != nullptr && strcasecmp(multi_release, "true") == 0) { cs->_is_multi_release_jar = true; } @@ -321,7 +324,7 @@ char* AOTClassLocation::read_manifest(JavaThread* current, const char* path, siz } // The result is resource allocated. -char* AOTClassLocation::get_cpattr() const { +char* AOTClassLocation::get_attr(const char* tag) const { if (_manifest_length == 0) { return nullptr; } @@ -337,7 +340,6 @@ char* AOTClassLocation::get_cpattr() const { // Remove all new-line continuation (remove all "\n " substrings) StringUtils::replace_no_expand(buf, "\n ", ""); - const char* tag = "Class-Path: "; size_t tag_len = strlen(tag); char* found = nullptr; char* line_start = buf; @@ -351,7 +353,13 @@ char* AOTClassLocation::get_cpattr() const { // JAR spec require the manifest file to be terminated by a new line. break; } - if (strncmp(tag, line_start, tag_len) == 0) { + + if (line_start == line_end) { + break; + } + + // Attribute names are case insensitive + if (strncasecmp(tag, line_start, tag_len) == 0) { if (found != nullptr) { // Same behavior as jdk/src/share/classes/java/util/jar/Attributes.java // If duplicated entries are found, the last one is used. @@ -370,6 +378,11 @@ char* AOTClassLocation::get_cpattr() const { return found; } +// The result is resource allocated. +char* AOTClassLocation::get_cpattr() const { + return get_attr("Class-Path: "); +} + AOTClassLocation* AOTClassLocation::write_to_archive() const { AOTClassLocation* archived_copy = (AOTClassLocation*)ArchiveBuilder::ro_region_alloc(total_size()); memcpy((char*)archived_copy, (char*)this, total_size()); @@ -719,7 +732,9 @@ bool AOTClassLocationConfig::is_valid_classpath_index(int classpath_index, Insta const char* const class_name = ik->name()->as_C_string(); const char* const file_name = ClassLoader::file_name_for_class_name(class_name, ik->name()->utf8_length()); - if (!zip->has_entry(current, file_name)) { + Handle class_loader(current, ik->class_loader()); + const AOTClassLocation* cl = AOTClassLocationConfig::class_location_at(classpath_index); + if (!zip->has_entry(current, file_name, class_loader, cl->is_multi_release_jar())) { aot_log_warning(aot)("class %s cannot be archived because it was not defined from %s as claimed", class_name, zip->name()); return false; diff --git a/src/hotspot/share/cds/aotClassLocation.hpp b/src/hotspot/share/cds/aotClassLocation.hpp index 771f4951671c..9a64e0deffae 100644 --- a/src/hotspot/share/cds/aotClassLocation.hpp +++ b/src/hotspot/share/cds/aotClassLocation.hpp @@ -106,6 +106,7 @@ class AOTClassLocation { // Only boot/app classpaths can contain unnamed module bool has_unnamed_module() const { return from_boot_classpath() || from_app_classpath(); } + char* get_attr(const char* tag) const; char* get_cpattr() const; AOTClassLocation* write_to_archive() const; diff --git a/src/hotspot/share/cds/aotMappedHeapWriter.cpp b/src/hotspot/share/cds/aotMappedHeapWriter.cpp index cfa6c460303e..8db7c6f3ff2d 100644 --- a/src/hotspot/share/cds/aotMappedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotMappedHeapWriter.cpp @@ -725,39 +725,26 @@ template void AOTMappedHeapWriter::mark_oop_pointer(T* buffered_add oopmap->set_bit(idx); } -void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop src_obj, Klass* src_klass) { +void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop src_obj, Klass* src_klass) { narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); address buffered_addr = requested_addr_to_buffered_addr(cast_from_oop
(requested_obj)); - oop fake_oop = cast_to_oop(buffered_addr); - if (UseCompactObjectHeaders) { - markWord prototype_header = src_klass->prototype_header().set_narrow_klass(nk); - fake_oop->set_mark(prototype_header); - } else { - fake_oop->set_narrow_klass(nk); - } + markWord mw = Arguments::is_valhalla_enabled() ? src_klass->prototype_header() : markWord::prototype(); + oopDesc* fake_oop = (oopDesc*)buffered_addr; - if (src_obj == nullptr) { - return; - } // We need to retain the identity_hash, because it may have been used by some hashtables // in the shared heap. - if (!src_obj->fast_no_hash_check() && (!(Arguments::is_valhalla_enabled() && src_obj->mark().is_inline_type()))) { + if (src_obj != nullptr && !src_obj->is_inline_type() && src_obj->has_identity_hash()) { intptr_t src_hash = src_obj->identity_hash(); - if (UseCompactObjectHeaders) { - fake_oop->set_mark(fake_oop->mark().copy_set_hash(src_hash)); - } else if (Arguments::is_valhalla_enabled()) { - fake_oop->set_mark(src_klass->prototype_header().copy_set_hash(src_hash)); - } else { - fake_oop->set_mark(markWord::prototype().copy_set_hash(src_hash)); - } - assert(fake_oop->mark().is_unlocked(), "sanity"); + mw = mw.copy_set_hash(src_hash); + } - DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash()); - assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash); + if (UseCompactObjectHeaders) { + fake_oop->set_mark(mw.set_narrow_klass(nk)); + } else { + fake_oop->set_mark(mw); + fake_oop->set_narrow_klass(nk); } - // Strip age bits. - fake_oop->set_mark(fake_oop->mark().set_age(0)); } class AOTMappedHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure { diff --git a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp index 8009e63e63d0..a8a5a5beb380 100644 --- a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp @@ -371,7 +371,7 @@ template void AOTStreamedHeapWriter::map_oop_field_in_buffer(oop ob void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_addr, oop src_obj, Klass* src_klass) { narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); - markWord mw = Arguments::enable_preview() ? src_klass->prototype_header() : markWord::prototype(); + markWord mw = Arguments::is_valhalla_enabled() ? src_klass->prototype_header() : markWord::prototype(); oopDesc* fake_oop = (oopDesc*)buffered_addr; // We need to retain the identity_hash, because it may have been used by some hashtables diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 7261fb1a5c6c..af0ae2c7a44a 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -389,7 +389,11 @@ char* DumpRegion::allocate_metaspace_obj(size_t num_bytes, address src, Metaspac assert(read_only == false, "only gaps in RW region are reusable"); char* gap_bottom = top(); char* gap_top = align_up(gap_bottom + RuntimeClassInfoPtrSize, alignment) - RuntimeClassInfoPtrSize; - size_t gap_bytes = _gap_tree.add_gap(gap_bottom, gap_top); + size_t gap_bytes = pointer_delta(gap_top, gap_bottom, 1); + // A gap smaller than an allocation unit can never be reused + if (gap_bytes >= SharedSpaceObjectAlignment) { + _gap_tree.add_gap(gap_bottom, gap_top); + } allocate(gap_bytes); } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 93d9061efb98..5402a5f9309d 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -909,7 +909,7 @@ void HeapShared::copy_and_rescan_aot_inited_mirror(InstanceKlass* ik) { void HeapShared::copy_java_mirror(oop orig_mirror, oop scratch_m) { // We need to retain the identity_hash, because it may have been used by some hashtables // in the shared heap. - if (!orig_mirror->fast_no_hash_check()) { + if (orig_mirror->has_identity_hash()) { intptr_t src_hash = orig_mirror->identity_hash(); if (UseCompactObjectHeaders) { narrowKlass nk = CompressedKlassPointers::encode(orig_mirror->klass()); @@ -918,7 +918,7 @@ void HeapShared::copy_java_mirror(oop orig_mirror, oop scratch_m) { // For valhalla, the prototype header is the same as markWord::prototype(); scratch_m->set_mark(markWord::prototype().copy_set_hash(src_hash)); } - assert(scratch_m->mark().is_unlocked(), "sanity"); + assert(scratch_m->mark().is_lock_neutral(), "sanity"); DEBUG_ONLY(intptr_t archived_hash = scratch_m->identity_hash()); assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash); diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 5cfb73d2f6ce..9b87438ff118 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -225,6 +225,9 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, cl_info, CHECK); + // The result InstanceKlass* is never used during the JVM process lifetime. + // We create it only for writing to the CDS archive, and so it need not be monitored by JVMTI or JFR. + assert(result->java_mirror() != nullptr, "must be"); RegeneratedClasses::add_class(InstanceKlass::cast(klass), result); diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp index 3c28bf06adf9..07b804c8ded4 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp @@ -34,6 +34,9 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "oops/klass.inline.hpp" +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif DumpTimeLambdaProxyClassInfo::~DumpTimeLambdaProxyClassInfo() { if (_proxy_klasses != nullptr) { @@ -318,6 +321,9 @@ InstanceKlass* LambdaProxyClassDictionary::find_lambda_proxy_class(const RunTime InstanceKlass* LambdaProxyClassDictionary::load_and_init_lambda_proxy_class(InstanceKlass* lambda_ik, InstanceKlass* caller_ik, TRAPS) { + + EventClassLoad class_load_event; + Handle class_loader(THREAD, caller_ik->class_loader()); Handle protection_domain; PackageEntry* pkg_entry = caller_ik->package(); @@ -359,20 +365,22 @@ InstanceKlass* LambdaProxyClassDictionary::load_and_init_lambda_proxy_class(Inst InstanceKlass* nest_host = caller_ik->nest_host(THREAD); assert(nest_host == shared_nest_host, "mismatched nest host"); - EventClassLoad class_load_event; + JFR_ONLY(Jfr::on_definition(lambda_ik, THREAD);) // Add to class hierarchy, and do possible deoptimizations. lambda_ik->add_to_hierarchy(THREAD); + assert(lambda_ik->is_loaded(), "Must be in at least loaded state"); // But, do not add to dictionary. + if (class_load_event.should_commit()) { + JFR_ONLY(SystemDictionary::post_class_load_event(&class_load_event, lambda_ik, ClassLoaderData::class_loader_data(class_loader()));) + } + lambda_ik->link_class(CHECK_NULL); // notify jvmti if (JvmtiExport::should_post_class_load()) { JvmtiExport::post_class_load(THREAD, lambda_ik); } - if (class_load_event.should_commit()) { - JFR_ONLY(SystemDictionary::post_class_load_event(&class_load_event, lambda_ik, ClassLoaderData::class_loader_data(class_loader()));) - } lambda_ik->initialize(CHECK_NULL); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index a84a7b4fb07d..62411a09556b 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -25,6 +25,7 @@ #include "cds/aotClassLocation.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" +#include "cds/cdsProtectionDomain.hpp" #include "cds/dynamicArchive.hpp" #include "cds/heapShared.hpp" #include "classfile/classFileStream.hpp" @@ -368,18 +369,57 @@ ClassPathZipEntry::~ClassPathZipEntry() { FREE_C_HEAP_ARRAY(_zip_name); } -bool ClassPathZipEntry::has_entry(JavaThread* current, const char* name) { - ThreadToNativeFromVM ttn(current); +bool ClassPathZipEntry::has_entry(JavaThread* current, const char* name, Handle class_loader, bool is_multi_release_jar) { // check whether zip archive contains name jint name_len; jint filesize; - jzentry* entry = ZipLibrary::find_entry(_zip, name, &filesize, &name_len); - if (entry == nullptr) { - return false; - } else { - ZipLibrary::free_entry(_zip, entry); - return true; + + { + ThreadToNativeFromVM ttn(current); + jzentry* entry = ZipLibrary::find_entry(_zip, name, &filesize, &name_len); + if (entry != nullptr) { + ZipLibrary::free_entry(_zip, entry); + return true; + } } + +#if INCLUDE_CDS + // Make an upcall to ClassLoader.getResource() if "name" is in a multi-release JAR + // and was not found in the root of the JAR file. This will always be a built-in class + // loader but CDS.getResource() will ensure the resource is retrieved from the correct + // JAR file anyway. + if (class_loader != nullptr && is_multi_release_jar) { + assert(SystemDictionaryShared::is_builtin_loader(ClassLoaderData::class_loader_data(class_loader())), "must be"); + JavaValue result(T_OBJECT); + oop class_name_oop = java_lang_String::create_oop_from_str(name, current); + oop zip_name_oop = CDSProtectionDomain::to_file_URL(_zip_name, Handle(), current); + Handle h_class_name(current, class_name_oop); + Handle h_zip_name(current, zip_name_oop); + + // URL ClassLoader.getResource(String name) + JavaCalls::call_static(&result, + vmClasses::CDS_klass(), + vmSymbols::getResource_name(), + vmSymbols::getResource_cds_signature(), + class_loader, + h_zip_name, + h_class_name, + current); + + // Not using CHECK, the thread must be checked manually + if (current->has_pending_exception()) { + current->clear_pending_exception(); + return false; + } + + assert(result.get_type() == T_OBJECT, "just checking"); + if (result.get_oop() != nullptr) { + return true; + } + } +#endif // INCLUDE_CDS + + return false; } u1* ClassPathZipEntry::open_entry(JavaThread* current, const char* name, jint* filesize, bool nul_terminate) { diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 2bdfdc0b39de..030e083374c8 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -93,7 +93,7 @@ class ClassPathZipEntry: public ClassPathEntry { const char* name() const { return _zip_name; } ClassPathZipEntry(jzfile* zip, const char* zip_name); virtual ~ClassPathZipEntry(); - bool has_entry(JavaThread* current, const char* name); + bool has_entry(JavaThread* current, const char* name, Handle class_loader, bool is_multi_release_jar); u1* open_entry(JavaThread* current, const char* name, jint* filesize, bool nul_terminate); ClassFileStream* open_stream(JavaThread* current, const char* name); }; diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index b773569ad7b8..27a899481a8f 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -81,6 +81,9 @@ #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = nullptr; @@ -899,6 +902,7 @@ void ClassLoaderData::free_deallocate_list() { HeapShared::remove_scratch_resolved_references((ConstantPool*)m); MetadataFactory::free_metadata(this, (ConstantPool*)m); } else if (m->is_klass()) { + JFR_ONLY(Jfr::on_deallocation(static_cast(m));) if (!((Klass*)m)->is_inline_klass()) { MetadataFactory::free_metadata(this, (InstanceKlass*)m); } else { diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index 4a3ec7b680ff..49cc3ea337b1 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -841,6 +841,64 @@ void FieldLayoutBuilder::prologue() { _root_group = new FieldGroup(); } +int FieldLayoutBuilder::add_field_to_group(FieldInfo fieldinfo, int idx, FieldGroup* group) { + BasicType type = Signature::basic_type(fieldinfo.signature(_constant_pool)); + switch(type) { + case T_BYTE: + case T_CHAR: + case T_DOUBLE: + case T_FLOAT: + case T_INT: + case T_LONG: + case T_SHORT: + case T_BOOLEAN: + group->add_primitive_field(idx, type); + return type2aelembytes(type); // alignment == size for primitive types + case T_OBJECT: + case T_ARRAY: + { + const bool is_inline_class = _is_inline_type || _is_abstract_value; + // Atomic flat fields can always be used in identity classes. + // Use them only for inline classes if the container is itself atomic. + const bool use_atomic_flat = !is_inline_class || _must_be_atomic; + LayoutKind lk = field_layout_selection(fieldinfo, _inline_layout_info_array, use_atomic_flat); + lk = adjust_with_budget(fieldinfo, _inline_layout_info_array, lk, _flattening_budget); + if (field_is_inlineable(fieldinfo, lk, _inline_layout_info_array)) { + _has_inlineable_fields = true; + } + + if (lk == LayoutKind::REFERENCE) { + if (group != _static_fields) { + _nonstatic_oopmap_count++; + } + group->add_oop_field(idx); + return type2aelembytes(type); // alignment == size for oops + } + + assert(group != _static_fields, "Static fields are not flattened"); + assert(lk != LayoutKind::BUFFERED && lk != LayoutKind::UNKNOWN, + "Invalid layout kind for flat field: %s", LayoutKindHelper::layout_kind_as_string(lk)); + + const int field_index = (int)fieldinfo.index(); + assert(_inline_layout_info_array != nullptr, "Array must have been created"); + assert(_inline_layout_info_array->adr_at(field_index)->klass() != nullptr, "Klass must have been set"); + _has_inlined_fields = true; + InlineKlass* vk = _inline_layout_info_array->adr_at(field_index)->klass(); + if (is_inline_class && !vk->is_naturally_atomic(LayoutKindHelper::is_null_free_flat(lk))) { + _has_non_naturally_atomic_fields = true; + } + group->add_flat_field(idx, vk, lk); + _inline_layout_info_array->adr_at(field_index)->set_kind(lk); + _nonstatic_oopmap_count += vk->nonstatic_oop_map_count(); + _field_info->adr_at(idx)->field_flags_addr()->update_flat(true); + _field_info->adr_at(idx)->set_layout_kind(lk); + return vk->layout_alignment(lk); + } + default: + fatal("Unexpected BasicType"); + } +} + // Field sorting for regular (non-inline) classes: // - fields are sorted in static and non-static fields // - non-static fields are also sorted according to their contention group @@ -869,52 +927,7 @@ void FieldLayoutBuilder::regular_field_sorting() { } } assert(group != nullptr, "invariant"); - BasicType type = Signature::basic_type(fieldinfo.signature(_constant_pool)); - switch(type) { - case T_BYTE: - case T_CHAR: - case T_DOUBLE: - case T_FLOAT: - case T_INT: - case T_LONG: - case T_SHORT: - case T_BOOLEAN: - group->add_primitive_field(idx, type); - break; - case T_OBJECT: - case T_ARRAY: - { - LayoutKind lk = field_layout_selection(fieldinfo, _inline_layout_info_array, true); - lk = adjust_with_budget(fieldinfo, _inline_layout_info_array, lk, _flattening_budget); - if (field_is_inlineable(fieldinfo, lk, _inline_layout_info_array)) { - _has_inlineable_fields = true; - } - - if (lk == LayoutKind::REFERENCE) { - if (group != _static_fields) _nonstatic_oopmap_count++; - group->add_oop_field(idx); - } else { - assert(group != _static_fields, "Static fields are not flattened"); - assert(lk != LayoutKind::BUFFERED && lk != LayoutKind::UNKNOWN, - "Invalid layout kind for flat field: %s", LayoutKindHelper::layout_kind_as_string(lk)); - - const int field_index = (int)fieldinfo.index(); - assert(_inline_layout_info_array != nullptr, "Array must have been created"); - assert(_inline_layout_info_array->adr_at(field_index)->klass() != nullptr, "Klass must have been set"); - _has_inlined_fields = true; - InlineKlass* vk = _inline_layout_info_array->adr_at(field_index)->klass(); - group->add_flat_field(idx, vk, lk); - _inline_layout_info_array->adr_at(field_index)->set_kind(lk); - _nonstatic_oopmap_count += vk->nonstatic_oop_map_count(); - _field_info->adr_at(idx)->field_flags_addr()->update_flat(true); - _field_info->adr_at(idx)->set_layout_kind(lk); - // no need to update _must_be_atomic if vk->must_be_atomic() is true because current class is not an inline class - } - break; - } - default: - fatal("Something wrong?"); - } + add_field_to_group(fieldinfo, idx, group); } _root_group->sort_by_size(); _static_fields->sort_by_size(); @@ -952,60 +965,7 @@ void FieldLayoutBuilder::inline_class_field_sorting() { group = _root_group; } assert(group != nullptr, "invariant"); - BasicType type = Signature::basic_type(fieldinfo.signature(_constant_pool)); - switch(type) { - case T_BYTE: - case T_CHAR: - case T_DOUBLE: - case T_FLOAT: - case T_INT: - case T_LONG: - case T_SHORT: - case T_BOOLEAN: - if (group != _static_fields) { - field_alignment = type2aelembytes(type); // alignment == size for primitive types - } - group->add_primitive_field(idx, type); - break; - case T_OBJECT: - case T_ARRAY: - { - bool use_atomic_flat = _must_be_atomic; // flatten atomic fields only if the container is itself atomic - LayoutKind lk = field_layout_selection(fieldinfo, _inline_layout_info_array, use_atomic_flat); - lk = adjust_with_budget(fieldinfo, _inline_layout_info_array, lk, _flattening_budget); - if (field_is_inlineable(fieldinfo, lk, _inline_layout_info_array)) { - _has_inlineable_fields = true; - } - - if (lk == LayoutKind::REFERENCE) { - if (group != _static_fields) { - _nonstatic_oopmap_count++; - field_alignment = type2aelembytes(type); // alignment == size for oops - } - group->add_oop_field(idx); - } else { - assert(group != _static_fields, "Static fields are not flattened"); - assert(lk != LayoutKind::BUFFERED && lk != LayoutKind::UNKNOWN, - "Invalid layout kind for flat field: %s", LayoutKindHelper::layout_kind_as_string(lk)); - - const int field_index = (int)fieldinfo.index(); - assert(_inline_layout_info_array != nullptr, "Array must have been created"); - assert(_inline_layout_info_array->adr_at(field_index)->klass() != nullptr, "Klass must have been set"); - _has_inlined_fields = true; - InlineKlass* vk = _inline_layout_info_array->adr_at(field_index)->klass(); - if (!vk->is_naturally_atomic(LayoutKindHelper::is_null_free_flat(lk))) _has_non_naturally_atomic_fields = true; - group->add_flat_field(idx, vk, lk); - _inline_layout_info_array->adr_at(field_index)->set_kind(lk); - _nonstatic_oopmap_count += vk->nonstatic_oop_map_count(); - field_alignment = vk->layout_alignment(lk); - _field_info->adr_at(idx)->field_flags_addr()->update_flat(true); - _field_info->adr_at(idx)->set_layout_kind(lk); - } - break; - } - default: - fatal("Unexpected BasicType"); - } + field_alignment = add_field_to_group(fieldinfo, idx, group); if (!fieldinfo.access_flags().is_static() && field_alignment > alignment) alignment = field_alignment; } _root_group->sort_by_size(); diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp index 38a44e431d0d..ad148e8441d3 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp @@ -341,6 +341,7 @@ class FieldLayoutBuilder : public ResourceObj { protected: void prologue(); void epilogue(); + int add_field_to_group(FieldInfo fieldinfo, int idx, FieldGroup* group); void regular_field_sorting(); void inline_class_field_sorting(); void add_flat_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, InlineKlass* vk, int offset); diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp index 10f49d83b610..8954de5610b0 100644 --- a/src/hotspot/share/classfile/stackMapTable.cpp +++ b/src/hotspot/share/classfile/stackMapTable.cpp @@ -271,6 +271,13 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { VerificationType* locals = nullptr; u1 frame_type = _stream->get_u1(CHECK_NULL); if (frame_type == EARLY_LARVAL) { + // early_larval frames are only supported in classes that support strict fields (preview classes) + if (!Verifier::supports_strict_fields(_verifier->current_class())) { + // reserved frame types when preview classes are disabled + _stream->stackmap_format_error( + "reserved frame type", CHECK_VERIFY_(_verifier, nullptr)); + } + u2 num_unset_fields = _stream->get_u2(CHECK_NULL); StackMapFrame::AssertUnsetFieldTable* new_fields = new StackMapFrame::AssertUnsetFieldTable(); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 6141eeb7bd04..dbbc4196c7f7 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -837,6 +837,7 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream( cl_info, CHECK_NULL); assert(k != nullptr, "no klass created"); + assert(k->class_loader_data() == loader_data, "invariant"); // Hidden classes that are not strong must update ClassLoaderData holder // so that they can be unloaded when the mirror is no longer referenced. @@ -844,8 +845,11 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream( k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror())); } + JFR_ONLY(Jfr::on_definition(k, THREAD);) + // Add to class hierarchy, and do possible deoptimizations. k->add_to_hierarchy(THREAD); + assert(k->is_loaded(), "Must be in at least loaded state"); // But, do not add to dictionary. if (class_load_event.should_commit()) { @@ -950,7 +954,6 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name, InstanceKlass* ik, PackageEntry* pkg_entry, Handle class_loader) { - assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(), "Cannot use sharing if java.base is patched"); @@ -1334,7 +1337,11 @@ void SystemDictionary::preload_class(Handle class_loader, InstanceKlass* ik, TRA ik->restore_unshareable_info(loader_data, pd, pkg_entry, CHECK); load_shared_class_misc(ik, loader_data); + + JFR_ONLY(Jfr::on_definition(ik, THREAD);) + ik->add_to_hierarchy(THREAD); + assert(ik->is_loaded(), "Must be in at least loaded state"); if (!ik->is_hidden()) { update_dictionary(THREAD, ik, loader_data); @@ -1343,8 +1350,6 @@ void SystemDictionary::preload_class(Handle class_loader, InstanceKlass* ik, TRA if (class_load_event.should_commit()) { JFR_ONLY(post_class_load_event(&class_load_event, ik, loader_data);) } - - assert(ik->is_loaded(), "Must be in at least loaded state"); } #endif // INCLUDE_CDS @@ -1572,8 +1577,11 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load JavaCalls::call(&result, m, &args, CHECK); } + JFR_ONLY(Jfr::on_definition(k, THREAD);) + // Add to class hierarchy, and do possible deoptimizations. k->add_to_hierarchy(THREAD); + assert(k->is_loaded(), "Must be in at least loaded state"); // Add to systemDictionary - so other classes can see it. // Grabs and releases SystemDictionary_lock diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 4852ebe533a6..7a5bb1ec64ab 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -344,10 +344,6 @@ class SystemDictionary : AllStatic { static InstanceKlass* find_or_define_instance_class(Symbol* class_name, Handle class_loader, InstanceKlass* k, TRAPS); - JFR_ONLY(static void post_class_load_event(EventClassLoad* event, - const InstanceKlass* k, - const ClassLoaderData* init_cld);) - public: static bool is_system_class_loader(oop class_loader); static bool is_platform_class_loader(oop class_loader); @@ -362,6 +358,10 @@ class SystemDictionary : AllStatic { // Return Symbol or throw exception if name given is can not be a valid Symbol. static Symbol* class_name_symbol(const char* name, Symbol* exception, TRAPS); + + JFR_ONLY(static void post_class_load_event(EventClassLoad* event, + const InstanceKlass* k, + const ClassLoaderData* init_cld);) }; #endif // SHARE_CLASSFILE_SYSTEMDICTIONARY_HPP diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index b0ded20b6f8c..626c28c17118 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -636,10 +636,9 @@ TypeOrigin ClassVerifier::ref_ctx(const char* sig) { return TypeOrigin::implicit(vt); } -static bool supports_strict_fields(InstanceKlass* klass) { +bool Verifier::supports_strict_fields(InstanceKlass* klass) { int ver = klass->major_version(); - return ver > Verifier::VALUE_TYPES_MAJOR_VERSION || - (ver == Verifier::VALUE_TYPES_MAJOR_VERSION && klass->minor_version() == Verifier::JAVA_PREVIEW_MINOR_VERSION); + return (ver >= Verifier::VALUE_TYPES_MAJOR_VERSION && klass->minor_version() == Verifier::JAVA_PREVIEW_MINOR_VERSION); } void ClassVerifier::verify_class(TRAPS) { @@ -2428,7 +2427,7 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, } } } - } else if (supports_strict_fields(_klass)) { + } else if (Verifier::supports_strict_fields(_klass)) { // `strict` fields are not writable, but only local fields produce verification errors if (is_local_field && fd.access_flags().is_strict() && fd.access_flags().is_final()) { verify_error(ErrorContext::bad_code(bci), diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp index 087750e4b121..97a546736a4a 100644 --- a/src/hotspot/share/classfile/verifier.hpp +++ b/src/hotspot/share/classfile/verifier.hpp @@ -69,6 +69,8 @@ class Verifier : AllStatic { // Print output for class+resolve static void trace_class_resolution(Klass* resolve_class, InstanceKlass* verify_class); + static bool supports_strict_fields(InstanceKlass* klass); + private: static Symbol* inference_verify( InstanceKlass* klass, char* msg, size_t msg_len, TRAPS); diff --git a/src/hotspot/share/classfile/vmClassMacros.hpp b/src/hotspot/share/classfile/vmClassMacros.hpp index 76071a550f94..2206da3684a5 100644 --- a/src/hotspot/share/classfile/vmClassMacros.hpp +++ b/src/hotspot/share/classfile/vmClassMacros.hpp @@ -138,6 +138,7 @@ do_klass(module_Modules_klass, jdk_internal_module_Modules ) \ \ /* support for CDS */ \ + do_klass(CDS_klass, jdk_internal_misc_CDS ) \ do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream ) \ do_klass(URL_klass, java_net_URL ) \ do_klass(Enum_klass, java_lang_Enum ) \ diff --git a/src/hotspot/share/classfile/vmClasses.cpp b/src/hotspot/share/classfile/vmClasses.cpp index 00d209a05ca5..1dde8b904a3c 100644 --- a/src/hotspot/share/classfile/vmClasses.cpp +++ b/src/hotspot/share/classfile/vmClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,9 @@ #include "oops/instanceStackChunkKlass.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/globals.hpp" +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif InstanceKlass* vmClasses::_klasses[static_cast(vmClassID::LIMIT)] = { nullptr /*, nullptr...*/ }; @@ -260,11 +263,15 @@ void vmClasses::resolve_shared_class(InstanceKlass* klass, ClassLoaderData* load klass->restore_unshareable_info(loader_data, domain, nullptr, THREAD); SystemDictionary::load_shared_class_misc(klass, loader_data); - Dictionary* dictionary = loader_data->dictionary(); - dictionary->add_klass(THREAD, klass->name(), klass); + + JFR_ONLY(Jfr::on_definition(klass, THREAD)); + klass->add_to_hierarchy(THREAD); assert(klass->is_loaded(), "Must be in at least loaded state"); + Dictionary* dictionary = loader_data->dictionary(); + dictionary->add_klass(THREAD, klass->name(), klass); + if (class_load_event.should_commit()) { JFR_ONLY(SystemDictionary::post_class_load_event(&class_load_event, klass, loader_data);) } diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 1de819967e09..f2fc6704d07f 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -750,6 +750,7 @@ class SerializeClosure; template(dumpSharedArchive_signature, "(ZLjava/lang/String;)Ljava/lang/String;") \ template(generateLambdaFormHolderClasses, "generateLambdaFormHolderClasses") \ template(generateLambdaFormHolderClasses_signature, "([Ljava/lang/String;)[Ljava/lang/Object;") \ + template(getResource_name, "getResource") \ template(getResourceAsByteArray_name, "getResourceAsByteArray") \ template(getResourceAsByteArray_signature, "(Ljava/lang/String;)[B") \ template(java_lang_Enum, "java/lang/Enum") \ @@ -759,6 +760,7 @@ class SerializeClosure; template(java_lang_invoke_DelegatingMethodHandle_Holder, "java/lang/invoke/DelegatingMethodHandle$Holder") \ template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \ template(jdk_internal_misc_CDS, "jdk/internal/misc/CDS") \ + template(getResource_cds_signature, "(Ljava/lang/ClassLoader;Ljava/net/URL;Ljava/lang/String;)Ljava/net/URL;")\ template(jdk_internal_vm_annotation_AOTSafeClassInitializer_signature, "Ljdk/internal/vm/annotation/AOTSafeClassInitializer;")\ template(java_util_concurrent_ConcurrentHashMap, "java/util/concurrent/ConcurrentHashMap") \ template(java_util_ArrayList, "java/util/ArrayList") \ diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index c36582f73813..30cd400058b5 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1388,7 +1388,6 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. _exception_cache = nullptr; _gc_data = nullptr; - _oops_do_mark_nmethods = nullptr; _oops_do_mark_link = nullptr; _compiled_ic_data = nullptr; diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 7ca7b57b43b7..3f1b5722f8fa 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -2169,8 +2169,12 @@ void CompileBroker::handle_full_code_cache(CodeBlobType code_blob_type) { #ifndef PRODUCT if (ExitOnFullCodeCache) { codecache_print(/* detailed= */ true); - before_exit(JavaThread::current()); - exit_globals(); // will delete tty + // handle_full_code_cache() can be called from a compiler thread while it + // is installing an nmethod, i.e. from a no-safepoint scope. before_exit() + // and exit_globals() acquire safepoint-checking locks (e.g. BeforeExit_lock) + // and would assert "Possible safepoint reached by thread that does not + // allow it". vm_direct_exit() terminates the VM without taking any such + // lock, which is sufficient for this diagnostic develop flag. vm_direct_exit(1); } #endif diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 774ea372bad8..cf4bacbb98b2 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -575,7 +575,7 @@ void G1BarrierSetC2::emit_stubs(CodeBuffer& cb) const { } stubs->at(i)->emit_code(masm); } - masm.flush(); + // Code will be copied. No ICache sync required. } #ifndef PRODUCT diff --git a/src/hotspot/share/gc/g1/g1CardSet.cpp b/src/hotspot/share/gc/g1/g1CardSet.cpp index f0db638a2fed..0f66e739362f 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.cpp +++ b/src/hotspot/share/gc/g1/g1CardSet.cpp @@ -967,7 +967,7 @@ class G1ContainerCardsClosure { void operator()(uint card_idx, uint length) { for (uint i = 0; i < length; i++) { - _cl.do_card(_region_idx, card_idx); + _cl.do_card(_region_idx, card_idx + i); } } }; diff --git a/src/hotspot/share/gc/g1/g1CodeRootSet.cpp b/src/hotspot/share/gc/g1/g1CodeRootSet.cpp index 7f1dec462d4f..771ab1a7fa2a 100644 --- a/src/hotspot/share/gc/g1/g1CodeRootSet.cpp +++ b/src/hotspot/share/gc/g1/g1CodeRootSet.cpp @@ -127,15 +127,6 @@ class G1CodeRootSetHashTable : public CHeapObj { } } - bool remove(nmethod* method) { - HashTableLookUp lookup(method); - bool removed = _table.remove(Thread::current(), lookup); - if (removed) { - _num_entries.sub_then_fetch(1u); - } - return removed; - } - bool contains(nmethod* method) { HashTableLookUp lookup(method); HashTableIgnore ignore; @@ -246,7 +237,9 @@ class G1CodeRootSetHashTable : public CHeapObj { _table_scanner.set(&_table, BucketClaimSize); } - size_t mem_size() { return sizeof(*this) + _table.get_mem_size(Thread::current()); } + size_t mem_size() { + return sizeof(*this) - sizeof(_table) + _table.get_mem_size(Thread::current()); + } size_t number_of_entries() const { return _num_entries.load_relaxed(); } }; @@ -281,11 +274,6 @@ G1CodeRootSet::~G1CodeRootSet() { delete _table; } -bool G1CodeRootSet::remove(nmethod* method) { - assert(!_is_iterating, "should not mutate while iterating the table"); - return _table->remove(method); -} - void G1CodeRootSet::bulk_remove() { assert(!_is_iterating, "should not mutate while iterating the table"); _table->bulk_remove(); diff --git a/src/hotspot/share/gc/g1/g1CodeRootSet.hpp b/src/hotspot/share/gc/g1/g1CodeRootSet.hpp index b298bbfb9148..c01a4a8396a5 100644 --- a/src/hotspot/share/gc/g1/g1CodeRootSet.hpp +++ b/src/hotspot/share/gc/g1/g1CodeRootSet.hpp @@ -43,7 +43,6 @@ class G1CodeRootSet { ~G1CodeRootSet(); void add(nmethod* method); - bool remove(nmethod* method); void bulk_remove(); // Notify the code root set that we are about to add the given // number of code roots. Only to be used during safepoint, not @@ -59,8 +58,6 @@ class G1CodeRootSet { // Remove all nmethods which no longer contain pointers into our "owner" region. void clean(G1HeapRegion* owner); - bool is_empty() { return length() == 0;} - // Length in elements size_t length() const; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 6d713ff8e1ef..833d07cb6852 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -127,16 +127,6 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; // apply to TLAB allocation, which is not part of this interface: it // is done by clients of this interface.) -void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) { - G1HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions); -} - -void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) { - // The from card cache is not the memory that is actually committed. So we cannot - // take advantage of the zero_filled parameter. - reset_from_card_cache(start_idx, num_regions); -} - // Collects commonly used scoped objects that are related to initial setup. class G1GCMark : StackObj { ResourceMark _rm; @@ -1306,7 +1296,6 @@ G1CollectedHeap::G1CollectedHeap() : _old_set("Old Region Set", new OldRegionSetChecker()), _humongous_set("Humongous Region Set", new HumongousRegionSetChecker()), _bot(nullptr), - _listener(), _numa(G1NUMA::create()), _hrm(), _allocator(nullptr), @@ -1332,7 +1321,7 @@ G1CollectedHeap::G1CollectedHeap() : _rem_set(nullptr), _card_set_config(), _card_set_freelist_pool(G1CardSetConfiguration::num_mem_object_types()), - _young_regions_cset_group(card_set_config(), &_card_set_freelist_pool, G1CSetCandidateGroup::YoungRegionId), + _young_regions_cset_group(card_set_config(), &_card_set_freelist_pool, G1CSetCandidateGroup::YoungId), _cm(nullptr), _cr(nullptr), _task_queues(nullptr), @@ -1502,7 +1491,6 @@ jint G1CollectedHeap::initialize() { heap_rs.base(), heap_rs.size(), page_size); - heap_storage->set_mapping_changed_listener(&_listener); // Create storage for the BOT, card table and the bitmap. G1RegionToSpaceMapper* bot_storage = @@ -1541,10 +1529,6 @@ jint G1CollectedHeap::initialize() { const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_num_regions() - 1) <= max_region_idx, "too many regions"); - // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not - // start within the first card. - guarantee((uintptr_t)(heap_rs.base()) >= G1CardTable::card_size(), "Java heap must not start within the first card."); - G1FromCardCache::initialize(max_num_regions()); // Also create a G1 rem set. _rem_set = new G1RemSet(this); _rem_set->initialize(max_num_regions()); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 5480b5684c41..1497c61f59dd 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -111,13 +111,6 @@ class G1STWSubjectToDiscoveryClosure : public BoolObjectClosure { bool do_object_b(oop p) override; }; -class G1RegionMappingChangedListener : public G1MappingChangedListener { - private: - void reset_from_card_cache(uint start_idx, size_t num_regions); - public: - void on_commit(uint start_idx, size_t num_regions, bool zero_filled) override; -}; - // Helper to claim contiguous sets of JavaThread for processing by multiple threads. class G1JavaThreadsListClaimer : public StackObj { ThreadsListHandle _list; @@ -223,9 +216,6 @@ class G1CollectedHeap : public CollectedHeap { // free_list_only is true, it will only rebuild the free list. void rebuild_region_sets(bool free_list_only); - // Callback for region mapping changed events. - G1RegionMappingChangedListener _listener; - // Handle G1 NUMA support. G1NUMA* _numa; diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index ca32759b54d3..efe8fe916591 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -218,7 +218,7 @@ void G1CollectionSet::add_young_region_common(G1HeapRegion* hr) { assert(hr->is_young(), "invariant"); assert(_inc_build_state == CSetBuildType::Active, "Precondition"); - // Add to remembered set/cardset group. + // Add to remembered set/cset group. _g1h->policy()->remset_tracker()->update_at_allocate(hr); _g1h->young_regions_cset_group()->add(hr); @@ -388,6 +388,11 @@ void G1CollectionSet::finalize_old_part(double time_remaining_ms) { if (candidates()->retained_groups().num_regions() > 0) { select_candidates_from_retained(time_remaining_ms); } + // Optional groups are selected separately from marking and retained candidate + // lists; sort the combined list to maintain the GC efficiency ordering. + _optional_groups.sort_by_efficiency(); + _optional_groups.verify(); + candidates()->verify(); } else { log_debug(gc, ergo, cset)("No candidates to reclaim."); @@ -413,7 +418,7 @@ void G1CollectionSet::add_optional_group(G1CSetCandidateGroup* group, double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) { uint num_expensive_regions = 0; - uint num_inital_regions = 0; + uint num_initial_regions = 0; uint num_initial_groups = 0; uint num_optional_regions = 0; @@ -424,8 +429,8 @@ double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) double optional_threshold_ms = time_remaining_ms * _policy->optional_prediction_fraction(); - uint min_old_cset_length = _policy->calc_min_old_cset_length(candidates()->last_marking_candidates_length()); - uint max_old_cset_length = MAX2(min_old_cset_length, _policy->calc_max_old_cset_length()); + uint min_num_old_cset_regions = _policy->calc_min_old_cset_length(candidates()->last_marking_candidates_length()); + uint max_num_old_cset_regions = MAX2(min_num_old_cset_regions, _policy->calc_max_old_cset_length()); bool check_time_remaining = _policy->use_adaptive_num_young_regions(); G1CSetCandidateGroupList* from_marking_groups = &candidates()->from_marking_groups(); @@ -435,13 +440,13 @@ double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) log_debug(gc, ergo, cset)("Start adding marking candidates to collection set. " "Min %u regions, max %u regions, available %u regions (%u groups), " "time remaining %1.2fms, optional threshold %1.2fms", - min_old_cset_length, max_old_cset_length, from_marking_groups->num_regions(), from_marking_groups->length(), + min_num_old_cset_regions, max_num_old_cset_regions, from_marking_groups->num_regions(), from_marking_groups->length(), time_remaining_ms, optional_threshold_ms); G1CSetCandidateGroupList selected_groups; for (G1CSetCandidateGroup* group : *from_marking_groups) { - if (num_inital_regions + num_optional_regions >= max_old_cset_length) { + if (num_initial_regions + num_optional_regions >= max_num_old_cset_regions) { // Added maximum number of old regions to the CSet. print_finish_message("Maximum number of regions reached", true); break; @@ -459,15 +464,15 @@ double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) } time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0); - // Add regions to old set until we reach the minimum amount - if (num_inital_regions < min_old_cset_length) { + // Add regions to old set until we reach the minimum amount or reach the optional threshold. + if (num_initial_regions < min_num_old_cset_regions || (check_time_remaining && time_remaining_ms > optional_threshold_ms)) { num_initial_groups++; add_group_to_collection_set(group); selected_groups.append(group); - num_inital_regions += group->length(); + num_initial_regions += group->length(); predicted_initial_time_ms += predicted_time_ms; // Record the number of regions added with no time remaining @@ -479,28 +484,15 @@ double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) // to the CSet if we reach the minimum. print_finish_message("Region amount reached min", true); break; + } else if (time_remaining_ms > 0) { + // Keep adding optional regions until time is up. + add_optional_group(group, + num_optional_regions, + predicted_optional_time_ms, + predicted_time_ms); } else { - // Keep adding regions to old set until we reach the optional threshold - if (time_remaining_ms > optional_threshold_ms) { - num_initial_groups++; - - add_group_to_collection_set(group); - selected_groups.append(group); - - num_inital_regions += group->length(); - - predicted_initial_time_ms += predicted_time_ms; - - } else if (time_remaining_ms > 0) { - // Keep adding optional regions until time is up. - add_optional_group(group, - num_optional_regions, - predicted_optional_time_ms, - predicted_time_ms); - } else { - print_finish_message("Predicted time too high", true); - break; - } + print_finish_message("Predicted time too high", true); + break; } } @@ -523,7 +515,7 @@ double G1CollectionSet::select_candidates_from_marking(double time_remaining_ms) selected_groups.num_regions(), selected_groups.length(), _optional_groups.num_regions(), _optional_groups.length(), predicted_initial_time_ms, predicted_optional_time_ms, time_remaining_ms); - assert(selected_groups.num_regions() == num_inital_regions, "must be"); + assert(selected_groups.num_regions() == num_initial_regions, "must be"); assert(_optional_groups.num_regions() == num_optional_regions, "must be"); return time_remaining_ms; } @@ -538,7 +530,7 @@ void G1CollectionSet::select_candidates_from_retained(double time_remaining_ms) double predicted_initial_time_ms = 0.0; double predicted_optional_time_ms = 0.0; - uint const min_regions = _policy->min_retained_old_cset_length(); + uint const min_num_regions = _policy->min_retained_old_cset_length(); // We want to make sure that on the one hand we process the retained regions asap, // but on the other hand do not take too many of them as optional regions. // So we split the time budget into budget we will unconditionally take into the @@ -552,7 +544,7 @@ void G1CollectionSet::select_candidates_from_retained(double time_remaining_ms) log_debug(gc, ergo, cset)("Start adding retained candidates to collection set. " "Min %u regions, available %u regions (%u groups), " "time remaining %1.2fms, optional remaining %1.2fms", - min_regions, retained_groups->num_regions(), retained_groups->length(), + min_num_regions, retained_groups->num_regions(), retained_groups->length(), time_remaining_ms, optional_time_remaining_ms); G1CSetCandidateGroupList remove_from_retained; @@ -585,10 +577,10 @@ void G1CollectionSet::select_candidates_from_retained(double time_remaining_ms) continue; } - if (fits_in_remaining_time || (num_expensive_regions < min_regions)) { + if (num_initial_regions < min_num_regions || fits_in_remaining_time) { predicted_initial_time_ms += predicted_time_ms; if (!fits_in_remaining_time) { - num_expensive_regions++; + num_expensive_regions += group->length(); } add_group_to_collection_set(group); @@ -622,7 +614,7 @@ void G1CollectionSet::select_candidates_from_retained(double time_remaining_ms) // for the regions in these groups. candidates()->remove(&remove_from_retained); - groups_to_abandon.clear(true /* uninstall_group_cardset */); + groups_to_abandon.clear(true /* uninstall_cset_group */); assert(num_optional_regions >= prev_num_optional_regions, "Sanity"); uint selected_optional_regions = num_optional_regions - prev_num_optional_regions; diff --git a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp index ac1b29a6bd79..84af28726a48 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp @@ -24,10 +24,9 @@ #include "gc/g1/g1CollectionSetCandidates.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" +#include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "utilities/growableArray.hpp" -uint G1CSetCandidateGroup::_next_group_id = G1CSetCandidateGroup::InitialId; - G1CSetCandidateGroup::G1CSetCandidateGroup(G1CardSetConfiguration* config, G1MonotonicArenaFreePool* card_set_freelist_pool, uint group_id) : _candidates(4, mtGCCardSet), _card_set_mm(config, card_set_freelist_pool), @@ -38,10 +37,16 @@ G1CSetCandidateGroup::G1CSetCandidateGroup(G1CardSetConfiguration* config, G1Mon { } G1CSetCandidateGroup::G1CSetCandidateGroup() : - G1CSetCandidateGroup(G1CollectedHeap::heap()->card_set_config(), G1CollectedHeap::heap()->card_set_freelist_pool(), _next_group_id++) + G1CSetCandidateGroup(G1CollectedHeap::heap()->card_set_config(), G1CollectedHeap::heap()->card_set_freelist_pool(), InvalidId) { } void G1CSetCandidateGroup::add(G1HeapRegion* hr) { + precond(hr->is_young() == (_group_id == YoungId)); + + if (_candidates.is_empty() && _group_id != YoungId) { + precond(_group_id == InvalidId); + _group_id = FirstNonYoungId + hr->hrm_index(); + } G1CollectionSetCandidateInfo c(hr); _candidates.append(c); hr->install_cset_group(this); @@ -63,16 +68,23 @@ double G1CSetCandidateGroup::liveness_percent() const { return ((capacity - _reclaimable_bytes) * 100.0) / capacity; } -void G1CSetCandidateGroup::clear(bool uninstall_group_cardset) { - if (uninstall_group_cardset) { +void G1CSetCandidateGroup::clear(bool uninstall_cset_group) { + clear_card_set(); + if (uninstall_cset_group) { for (G1CollectionSetCandidateInfo ci : _candidates) { G1HeapRegion* r = ci._r; r->uninstall_cset_group(); - r->rem_set()->clear(true /* only_cardset */); + r->rem_set()->set_state_untracked(); } } - _card_set.clear(); _candidates.clear(); + if (_group_id != YoungId) { + _group_id = InvalidId; + } +} + +void G1CSetCandidateGroup::clear_card_set() { + _card_set.clear(); } double G1CSetCandidateGroup::predict_group_total_time_ms() const { @@ -116,16 +128,24 @@ double G1CSetCandidateGroup::predict_group_total_time_ms() const { } int G1CSetCandidateGroup::compare_gc_efficiency(G1CSetCandidateGroup** gr1, G1CSetCandidateGroup** gr2) { - double gc_eff1 = (*gr1)->gc_efficiency(); - double gc_eff2 = (*gr2)->gc_efficiency(); + G1CSetCandidateGroup* group_1 = *gr1; + G1CSetCandidateGroup* group_2 = *gr2; + double gc_eff1 = group_1->gc_efficiency(); + double gc_eff2 = group_2->gc_efficiency(); if (gc_eff1 > gc_eff2) { return -1; } else if (gc_eff1 < gc_eff2) { return 1; - } else { - return 0; } + + // Make ordering deterministic by breaking ties with group ids. + if (group_1->group_id() < group_2->group_id()) { + return -1; + } else if (group_1->group_id() > group_2->group_id()) { + return 1; + } + return 0; } G1CSetCandidateGroupList::G1CSetCandidateGroupList() : _groups(8, mtGC), _num_regions(0) { } @@ -141,9 +161,9 @@ G1CSetCandidateGroup* G1CSetCandidateGroupList::at(uint index) { return _groups.at(index); } -void G1CSetCandidateGroupList::clear(bool uninstall_group_cardset) { +void G1CSetCandidateGroupList::clear(bool uninstall_cset_group) { for (G1CSetCandidateGroup* gr : _groups) { - gr->clear(uninstall_group_cardset); + gr->clear(uninstall_cset_group); delete gr; } _groups.clear(); @@ -232,8 +252,8 @@ void G1CollectionSetCandidates::initialize(uint max_regions) { } void G1CollectionSetCandidates::clear() { - _retained_groups.clear(true /* uninstall_group_cardset */); - _from_marking_groups.clear(true /* uninstall_group_cardset */); + _retained_groups.clear(true /* uninstall_cset_group */); + _from_marking_groups.clear(true /* uninstall_cset_group */); for (uint i = 0; i < _max_regions; i++) { _contains_map[i] = CandidateOrigin::Invalid; } @@ -267,7 +287,6 @@ void G1CollectionSetCandidates::set_candidates_from_marking(GrowableArrayCHeapcalc_min_old_cset_length(num_candidates); - G1CSetCandidateGroup::reset_next_group_id(); G1CSetCandidateGroup* current = nullptr; current = new G1CSetCandidateGroup(); @@ -345,6 +364,7 @@ void G1CollectionSetCandidates::add_retained_region_unsorted(G1HeapRegion* r) { G1CSetCandidateGroup* gr = new G1CSetCandidateGroup(); gr->add(r); + gr->calculate_efficiency(); _retained_groups.append(gr); } diff --git a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp index a70f9e395b64..368022a586c1 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp @@ -73,23 +73,17 @@ class G1CSetCandidateGroup : public CHeapObj{ size_t _reclaimable_bytes; double _gc_efficiency; + // The _group_id identifies a candidate group in logging and in the + // FromCardCache. A group id must be assigned to at most one cset group + // at any time. + uint _group_id; public: - // The _group_id uniquely identifies a candidate group when printing, making it - // easier to associate regions with their assigned G1CSetCandidateGroup, if any. - // Special values for the id: - // * id 0 is reserved for regions that do not have a remembered set. - // * id 1 is reserved for the G1CollectionSetCandidate that contains all young regions. - // * other ids are handed out incrementally, starting from InitialId. - static const uint NoRemSetId = 0; - static const uint YoungRegionId = 1; - static const uint InitialId = 2; + static constexpr uint NoGroupId = 0; + static constexpr uint YoungId = NoGroupId + 1; + static constexpr uint FirstNonYoungId = YoungId + 1; + static constexpr uint InvalidId = UINT_MAX; -private: - const uint _group_id; - static uint _next_group_id; - -public: G1CSetCandidateGroup(); G1CSetCandidateGroup(G1CardSetConfiguration* config, G1MonotonicArenaFreePool* card_set_freelist_pool, uint group_id); ~G1CSetCandidateGroup() { @@ -127,7 +121,10 @@ class G1CSetCandidateGroup : public CHeapObj{ return _card_set.occupied(); } - void clear(bool uninstall_group_cardset = false); + // Clear the group-owned card set. + void clear_card_set(); + + void clear(bool uninstall_cset_group = false); G1CSetCandidateGroupIterator begin() const { return _candidates.begin(); @@ -137,10 +134,9 @@ class G1CSetCandidateGroup : public CHeapObj{ return _candidates.end(); } - uint group_id() const { return _group_id; } - - static void reset_next_group_id() { - _next_group_id = InitialId; + uint group_id() const { + assert(_group_id != InvalidId, "group must have an assigned id"); + return _group_id; } }; @@ -154,11 +150,11 @@ class G1CSetCandidateGroupList { G1CSetCandidateGroupList(); void append(G1CSetCandidateGroup* group); - // Delete all groups from the list. The cardset cleanup for regions within the - // groups could have been done elsewhere (e.g. when adding groups to the - // collection set or to retained regions). The uninstall_group_cardset is set to + // Delete all groups from the list. The card set cleanup for regions within + // the groups could have been done elsewhere (e.g. when adding groups to the + // collection set or to retained regions). The uninstall_cset_group is set to // true if cleanup needs to happen as we clear the groups from the list. - void clear(bool uninstall_group_cardset = false); + void clear(bool uninstall_cset_group = false); G1CSetCandidateGroup* at(uint index); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 2246ffc12e7f..ccac7e01db07 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -36,7 +36,6 @@ #include "gc/g1/g1ConcurrentMarkRemarkTasks.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRebuildAndScrub.hpp" -#include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionManager.hpp" #include "gc/g1/g1HeapRegionPrinter.hpp" @@ -448,7 +447,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _finger(nullptr), // _finger set in set_non_marking_state - _worker_id_offset(G1ConcRefinementThreads), // The refinement control thread does not refine cards, so it's just the worker threads. _max_num_tasks(MAX2(ConcGCThreads, ParallelGCThreads)), _num_active_tasks(0), // _num_active_tasks set in set_non_marking_state() _tasks(nullptr), @@ -502,7 +500,7 @@ void G1ConcurrentMark::fully_initialize() { vm_shutdown_during_initialization("Could not create ConcurrentMarkThread"); } - log_debug(gc)("ConcGCThreads: %u offset %u", ConcGCThreads, _worker_id_offset); + log_debug(gc)("ConcGCThreads: %u", ConcGCThreads); log_debug(gc)("ParallelGCThreads: %u", ParallelGCThreads); _max_concurrent_workers = ConcGCThreads; @@ -3161,7 +3159,7 @@ bool G1PrintRegionLivenessInfoClosure::do_heap_region(G1HeapRegion* r) { const char* remset_type = r->rem_set()->get_short_state_str(); uint cset_group_id = r->rem_set()->has_cset_group() ? r->rem_set()->cset_group_id() - : G1CSetCandidateGroup::NoRemSetId; + : G1CSetCandidateGroup::NoGroupId; _total_used_bytes += used_bytes; _total_capacity_bytes += capacity_bytes; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index 925d250ab0ad..ca36b48de5b4 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -354,7 +354,6 @@ class G1ConcurrentMark : public CHeapObj { // always pointing to the end of the // last claimed region - uint _worker_id_offset; uint _max_num_tasks; // Maximum number of marking tasks uint _num_active_tasks; // Number of tasks currently active G1CMTask** _tasks; // Task queue array (max_worker_id length) @@ -567,8 +566,6 @@ class G1ConcurrentMark : public CHeapObj { // TARS for the given region during remembered set rebuilding. inline HeapWord* top_at_rebuild_start(G1HeapRegion* r) const; - uint worker_id_offset() const { return _worker_id_offset; } - // Fully allocates and initializes data structures for the concurrent cycle. // Methods that use concurrent cycle state such as the concurrent mark threads, // tasks, marking stack, statistics, TAMS or TARS require this initialization. diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkRemarkTasks.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkRemarkTasks.cpp index a7fcc566d618..61ec542c71f0 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkRemarkTasks.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkRemarkTasks.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionPrinter.hpp" +#include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1RemSetTrackingPolicy.hpp" #include "logging/log.hpp" #include "runtime/mutexLocker.hpp" @@ -208,7 +209,8 @@ void G1UpdateRegionLivenessAndSelectForRebuildTask::prune(GrowableArrayCHeap allowed_waste) { break; } - r->rem_set()->clear(true /* cardset_only */); + assert(!r->rem_set()->has_cset_group(), "must not have a cset group"); + r->rem_set()->set_state_untracked(); wasted_bytes += reclaimable; num_pruned++; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp index 5b652f096a76..cf3e07592a09 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp @@ -93,8 +93,11 @@ class G1RebuildRSAndScrubTask : public WorkerTask { reset_processed_words(); // If a yield occurs (potential young-gc pause), must recheck for // potential regions reclamation. - if (_cm->do_yield_check() && !should_rebuild_or_scrub(hr)) { - return true; + if (_cm->do_yield_check()) { + _rebuild_closure.reset_from_card_cache(); + if (!should_rebuild_or_scrub(hr)) { + return true; + } } } return _cm->has_aborted() || !should_rebuild_or_scrub(hr); @@ -245,16 +248,18 @@ class G1RebuildRSAndScrubTask : public WorkerTask { } public: - G1RebuildRSAndScrubRegionClosure(G1ConcurrentMark* cm, bool should_rebuild_remset, uint worker_id) : + G1RebuildRSAndScrubRegionClosure(G1ConcurrentMark* cm, bool should_rebuild_remset) : _cm(cm), _bitmap(_cm->mark_bitmap()), - _rebuild_closure(G1CollectedHeap::heap(), worker_id + cm->worker_id_offset()), + _rebuild_closure(G1CollectedHeap::heap()), _should_rebuild_remset(should_rebuild_remset), _processed_words(0) { } bool do_heap_region(G1HeapRegion* hr) { // Avoid stalling safepoints and stop iteration if mark cycle has been aborted. - _cm->do_yield_check(); + if (_cm->do_yield_check()) { + _rebuild_closure.reset_from_card_cache(); + } if (_cm->has_aborted()) { return true; } @@ -294,7 +299,7 @@ class G1RebuildRSAndScrubTask : public WorkerTask { SuspendibleThreadSetJoiner sts_join; G1CollectedHeap* g1h = G1CollectedHeap::heap(); - G1RebuildRSAndScrubRegionClosure cl(_cm, _should_rebuild_remset, worker_id); + G1RebuildRSAndScrubRegionClosure cl(_cm, _should_rebuild_remset); g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hr_claimer, worker_id); } }; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineSweepTask.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineSweepTask.cpp index b0cf8353dfb8..d50c31f3da48 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineSweepTask.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineSweepTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,6 @@ class G1RefineRegionClosure : public G1HeapRegionClosure { G1RemSet* _rem_set; G1CardTableClaimTable* _scan_state; - uint _worker_id; - bool has_work(G1HeapRegion* r) { return _scan_state->has_unclaimed_cards(r->hrm_index()); } @@ -55,7 +53,7 @@ class G1RefineRegionClosure : public G1HeapRegionClosure { void do_dirty_card(CardValue* source_card, CardValue* dest_card) { verify_card_pair_refers_to_same_card(source_card, dest_card); - G1RemSet::RefineResult res = _rem_set->refine_card_concurrently(source_card, _worker_id); + G1RemSet::RefineResult res = _rem_set->refine_card_concurrently(source_card); // Gather statistics based on the result. switch (res) { case G1RemSet::HasRefToCSet: { @@ -94,11 +92,10 @@ class G1RefineRegionClosure : public G1HeapRegionClosure { bool _completed; G1LocalRefineStats _per_worker_refine_data; - G1RefineRegionClosure(uint worker_id, G1CardTableClaimTable* scan_state) : + G1RefineRegionClosure(G1CardTableClaimTable* scan_state) : G1HeapRegionClosure(), _rem_set(G1CollectedHeap::heap()->rem_set()), _scan_state(scan_state), - _worker_id(worker_id), _completed(true), _per_worker_refine_data() { } @@ -164,8 +161,8 @@ class G1RefineRegionClosure : public G1HeapRegionClosure { }; G1ConcurrentRefineSweepTask::G1ConcurrentRefineSweepTask(G1CardTableClaimTable* scan_state, - G1ConcurrentRefineStats* stats, - uint max_workers) : + G1ConcurrentRefineStats* stats, + uint max_workers) : WorkerTask("G1 Refine Task"), _scan_state(scan_state), _stats(stats), @@ -176,7 +173,7 @@ G1ConcurrentRefineSweepTask::G1ConcurrentRefineSweepTask(G1CardTableClaimTable* void G1ConcurrentRefineSweepTask::work(uint worker_id) { jlong start = os::elapsed_counter(); - G1RefineRegionClosure sweep_cl(worker_id, _scan_state); + G1RefineRegionClosure sweep_cl(_scan_state); _scan_state->heap_region_iterate_from_worker_offset(&sweep_cl, worker_id, _max_workers); if (!sweep_cl._completed) { diff --git a/src/hotspot/share/gc/g1/g1FromCardCache.cpp b/src/hotspot/share/gc/g1/g1FromCardCache.cpp deleted file mode 100644 index 8f5c84da0e3e..000000000000 --- a/src/hotspot/share/gc/g1/g1FromCardCache.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "gc/g1/g1FromCardCache.hpp" -#include "gc/shared/gc_globals.hpp" -#include "memory/padded.inline.hpp" -#include "runtime/globals.hpp" -#include "utilities/debug.hpp" - -uintptr_t** G1FromCardCache::_cache = nullptr; -uint G1FromCardCache::_max_reserved_regions = 0; -size_t G1FromCardCache::_static_mem_size = 0; -#ifdef ASSERT -uint G1FromCardCache::_max_workers = 0; -#endif - -void G1FromCardCache::initialize(uint max_reserved_regions) { - guarantee(max_reserved_regions > 0, "Heap size must be valid"); - guarantee(_cache == nullptr, "Should not call this multiple times"); - - _max_reserved_regions = max_reserved_regions; -#ifdef ASSERT - _max_workers = num_par_rem_sets(); -#endif - _cache = Padded2DArray::create_unfreeable(_max_reserved_regions, - num_par_rem_sets(), - &_static_mem_size); - - if (AlwaysPreTouch) { - invalidate(0, _max_reserved_regions); - } -} - -void G1FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { - guarantee((size_t)start_idx + new_num_regions <= max_uintx, - "Trying to invalidate beyond maximum region, from %u size %zu", - start_idx, new_num_regions); - uint end_idx = (start_idx + (uint)new_num_regions); - assert(end_idx <= _max_reserved_regions, "Must be within max."); - - for (uint i = 0; i < num_par_rem_sets(); i++) { - for (uint j = start_idx; j < end_idx; j++) { - set(i, j, InvalidCard); - } - } -} - -#ifndef PRODUCT -void G1FromCardCache::print(outputStream* out) { - for (uint i = 0; i < num_par_rem_sets(); i++) { - for (uint j = 0; j < _max_reserved_regions; j++) { - out->print_cr("_from_card_cache[%u][%u] = %zu.", - i, j, at(i, j)); - } - } -} -#endif - -uint G1FromCardCache::num_par_rem_sets() { - return G1ConcRefinementThreads + ConcGCThreads; -} - -void G1FromCardCache::clear(uint region_idx) { - uint num_par_remsets = num_par_rem_sets(); - for (uint i = 0; i < num_par_remsets; i++) { - set(i, region_idx, InvalidCard); - } -} diff --git a/src/hotspot/share/gc/g1/g1FromCardCache.hpp b/src/hotspot/share/gc/g1/g1FromCardCache.hpp index 0a01e0102aed..5f759be0c4fb 100644 --- a/src/hotspot/share/gc/g1/g1FromCardCache.hpp +++ b/src/hotspot/share/gc/g1/g1FromCardCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,76 +25,44 @@ #ifndef SHARE_GC_G1_G1FROMCARDCACHE_HPP #define SHARE_GC_G1_G1FROMCARDCACHE_HPP -#include "memory/allStatic.hpp" -#include "utilities/ostream.hpp" +#include "gc/shared/gc_globals.hpp" +#include "oops/oopsHierarchy.hpp" +#include "utilities/globalDefinitions.hpp" -// G1FromCardCache remembers the most recently processed card on the heap on -// a per-region and per-thread basis. -class G1FromCardCache : public AllStatic { -private: - // Array of card indices. Indexed by heap region (rows) and thread (columns) to minimize - // thread contention. - // This order minimizes the time to clear all entries for a given region during region - // freeing. I.e. a single clear of a single memory area instead of multiple separate - // accesses with a large stride per region. - static uintptr_t** _cache; - static uint _max_reserved_regions; - static size_t _static_mem_size; -#ifdef ASSERT - static uint _max_workers; +// G1FromCardCache remembers which destination cset groups have been +// encountered while a worker scans the current from_card. +// +// Refinement and remembered set rebuild scan the heap linearly, visiting +// references from a card consecutively. Therefore, the cache only tracks +// the destination cset groups found while scanning the current card. The +// cache state is discarded when advancing to the next card. +// +// A scan can be suspended at a yield point. A GC may run while it is +// suspended and change the cset group assignments. Therefore, the cache +// must be reset before the scan resumes after every yield. +class G1FromCardCache { + // Worst case: each reference in a card targets a different cset group. + static constexpr uint MaxGroupsPerCard = MaxGCCardSizeInBytes / sizeof(narrowOop); - static void check_bounds(uint worker_id, uint region_idx) { - assert(worker_id < _max_workers, "Worker_id %u is larger than maximum %u", worker_id, _max_workers); - assert(region_idx < _max_reserved_regions, "Region_idx %u is larger than maximum %u", region_idx, _max_reserved_regions); - } -#endif - - // This card index indicates "no card for that entry" yet. This allows us to use the OS - // lazy backing of memory with zero-filled pages to avoid initial actual memory use. - // This means that the heap must not contain card zero. - static const uintptr_t InvalidCard = 0; + uintptr_t _from_card; + uint _num_cset_groups; + uint _cset_group_ids[MaxGroupsPerCard]; - // Gives an approximation on how many threads can be expected to add records to - // a remembered set in parallel. This is used for sizing the G1FromCardCache to - // decrease performance losses due to data structure sharing. - // Examples for quantities that influence this value are the maximum number of - // mutator threads, maximum number of concurrent refinement or GC threads. - static uint num_par_rem_sets(); + NONCOPYABLE(G1FromCardCache); public: - static void clear(uint region_idx); - - // Returns true if the given card is in the cache at the given location, or - // replaces the card at that location and returns false. - static bool contains_or_replace(uint worker_id, uint region_idx, uintptr_t card) { - uintptr_t card_in_cache = at(worker_id, region_idx); - if (card_in_cache == card) { - return true; - } else { - set(worker_id, region_idx, card); - return false; - } - } - - static uintptr_t at(uint worker_id, uint region_idx) { - DEBUG_ONLY(check_bounds(worker_id, region_idx);) - return _cache[region_idx][worker_id]; - } + G1FromCardCache() + : _from_card(0), + _num_cset_groups(0) {} - static void set(uint worker_id, uint region_idx, uintptr_t val) { - DEBUG_ONLY(check_bounds(worker_id, region_idx);) - _cache[region_idx][worker_id] = val; + // Discard the state associated with the _from_card. + void reset() { + _num_cset_groups = 0; } - static void initialize(uint max_reserved_regions); - - static void invalidate(uint start_idx, size_t num_regions); - - static void print(outputStream* out = tty) PRODUCT_RETURN; - - static size_t static_mem_size() { - return _static_mem_size; - } + // Returns true if cset_group_id has already been encountered while + // scanning from_card. Otherwise, records the id and returns false. + inline bool contains_or_add(uintptr_t from_card, uint cset_group_id); }; #endif // SHARE_GC_G1_G1FROMCARDCACHE_HPP diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java b/src/hotspot/share/gc/g1/g1FromCardCache.inline.hpp similarity index 58% rename from test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java rename to src/hotspot/share/gc/g1/g1FromCardCache.inline.hpp index 6df788cf3548..9a4abac3bc81 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java +++ b/src/hotspot/share/gc/g1/g1FromCardCache.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,26 +19,30 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. + * */ +#ifndef SHARE_GC_G1_G1FROMCARDCACHE_INLINE_HPP +#define SHARE_GC_G1_G1FROMCARDCACHE_INLINE_HPP -/* - * @test - * @modules java.base/jdk.internal.misc:+open - * - * @summary converted from VM Testbase metaspace/gc/firstGC_50m. - * VM Testbase keywords: [nonconcurrent, quarantine] - * VM Testbase comments: 8208250 - * - * @library /vmTestbase /test/lib - * @run main/othervm - * -Xms200m - * -Xlog:gc+heap=trace,gc:gc.log - * -XX:MetaspaceSize=50m - * -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions - * -XX:-VerifyBeforeExit - * -XX:-UseCompressedOops - * metaspace.gc.FirstGCTest - */ +#include "gc/g1/g1FromCardCache.hpp" + +bool G1FromCardCache::contains_or_add(uintptr_t from_card, uint cset_group_id) { + if (_from_card != from_card) { + _from_card = from_card; + _num_cset_groups = 0; + } + + for (uint i = 0; i < _num_cset_groups; i++) { + if (_cset_group_ids[i] == cset_group_id) { + return true; + } + } + + assert(_num_cset_groups < MaxGroupsPerCard, "from_card has too many destination cset groups"); + + _cset_group_ids[_num_cset_groups++] = cset_group_id; + return false; +} +#endif // SHARE_GC_G1_G1FROMCARDCACHE_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1FullGCResetMetadataTask.cpp b/src/hotspot/share/gc/g1/g1FullGCResetMetadataTask.cpp index 310cc4297c67..d6d39bafb34e 100644 --- a/src/hotspot/share/gc/g1/g1FullGCResetMetadataTask.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCResetMetadataTask.cpp @@ -31,8 +31,14 @@ G1FullGCResetMetadataTask::G1ResetMetadataClosure::G1ResetMetadataClosure(G1Full _collector(collector) { } void G1FullGCResetMetadataTask::G1ResetMetadataClosure::reset_region_metadata(G1HeapRegion* hr) { - assert(hr->is_humongous() || !hr->rem_set()->has_cset_group(), - "Non-humongous regions must not have cset group"); + if (hr->rem_set()->has_cset_group()) { + assert(hr->is_starts_humongous(), "Only humongous regions can retain a cset group"); + assert(hr->rem_set()->cset_group()->length() == 1, + "Humongous region cset group must contain exactly one region"); + + hr->rem_set()->cset_group()->clear_card_set(); + } + hr->rem_set()->clear(); hr->clear_both_card_tables(); _g1h->concurrent_mark()->reset_region_marking_state(hr); diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.cpp b/src/hotspot/share/gc/g1/g1HeapRegion.cpp index 2c85e2fcc0d5..a9a76eee634f 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegion.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegion.cpp @@ -109,7 +109,12 @@ void G1HeapRegion::handle_evacuation_failure(bool retain) { move_to_old(); _rem_set->clean_code_roots(this); - _rem_set->clear(true /* only_cardset */, retain /* keep_tracked */); + assert(!_rem_set->has_cset_group(), "must not have a cset group"); + if (retain) { + assert(_rem_set->is_tracked(), "must be"); + } else { + _rem_set->set_state_untracked(); + } } void G1HeapRegion::unlink_from_list() { @@ -263,7 +268,7 @@ G1HeapRegion::G1HeapRegion(uint hrm_index, assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()), "invalid space boundaries"); - _rem_set = new G1HeapRegionRemSet(this); + _rem_set = new G1HeapRegionRemSet(); initialize(); } @@ -391,7 +396,7 @@ bool G1HeapRegion::verify_code_roots(VerifyOption vo) const { } G1HeapRegionRemSet* hrrs = rem_set(); - size_t code_roots_length = hrrs->code_roots_list_length(); + size_t code_roots_length = hrrs->code_roots_length(); // if this region is empty then there should be no entries // on its code root list diff --git a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.cpp b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.cpp index e2009b0e77d4..a965859a4146 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.cpp @@ -22,24 +22,8 @@ * */ -#include "gc/g1/g1BlockOffsetTable.inline.hpp" -#include "gc/g1/g1CardSetContainers.inline.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1ConcurrentRefine.hpp" -#include "gc/g1/g1HeapRegionManager.inline.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" -#include "memory/allocation.hpp" -#include "memory/padded.inline.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/globals_extension.hpp" -#include "runtime/java.hpp" -#include "runtime/mutexLocker.hpp" -#include "utilities/bitMap.inline.hpp" -#include "utilities/debug.hpp" -#include "utilities/formatBuffer.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/growableArray.hpp" -#include "utilities/powerOfTwo.hpp" +#include "utilities/ostream.hpp" HeapWord* G1HeapRegionRemSet::_heap_base_address = nullptr; @@ -55,36 +39,19 @@ void G1HeapRegionRemSet::uninstall_cset_group() { _cset_group = nullptr; } -G1HeapRegionRemSet::G1HeapRegionRemSet(G1HeapRegion* hr) : +G1HeapRegionRemSet::G1HeapRegionRemSet() : _code_roots(), _cset_group(nullptr), - _hr(hr), _state(Untracked) { } G1HeapRegionRemSet::~G1HeapRegionRemSet() { assert(!has_cset_group(), "Still assigned to a CSet group"); } -void G1HeapRegionRemSet::clear_fcc() { - G1FromCardCache::clear(_hr->hrm_index()); -} - -void G1HeapRegionRemSet::clear(bool only_cardset, bool keep_tracked) { - if (!only_cardset) { - _code_roots.clear(); - } - clear_fcc(); - - if (has_cset_group()) { - card_set()->clear(); - assert(card_set()->occupied() == 0, "Should be clear."); - } - - if (!keep_tracked) { - set_state_untracked(); - } else { - assert(is_tracked(), "must be"); - } +void G1HeapRegionRemSet::clear() { + assert(card_set_is_empty(), "Card set must be empty"); + _code_roots.clear(); + set_state_untracked(); } void G1HeapRegionRemSet::reset_code_root_table_scanner() { @@ -108,26 +75,12 @@ void G1HeapRegionRemSet::print_static_mem_size(outputStream* out) { } // Code roots support -// -// The code root set is protected by two separate locking schemes -// When at safepoint the per-hrrs lock must be held during modifications -// except when doing a full gc. -// When not at safepoint the CodeCache_lock must be held during modifications. void G1HeapRegionRemSet::add_code_root(nmethod* nm) { assert(nm != nullptr, "sanity"); _code_roots.add(nm); } -void G1HeapRegionRemSet::remove_code_root(nmethod* nm) { - assert(nm != nullptr, "sanity"); - - _code_roots.remove(nm); - - // Check that there were no duplicates - guarantee(!_code_roots.contains(nm), "duplicate entry found"); -} - void G1HeapRegionRemSet::bulk_remove_code_roots() { _code_roots.bulk_remove(); } diff --git a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp index b185aa3151c2..2552df58b3a3 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp @@ -29,13 +29,8 @@ #include "gc/g1/g1CardSetMemory.hpp" #include "gc/g1/g1CodeRootSet.hpp" #include "gc/g1/g1CollectionSetCandidates.hpp" -#include "gc/g1/g1FromCardCache.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/safepoint.hpp" -#include "utilities/bitMap.hpp" -class G1CardSetMemoryManager; -class G1CSetCandidateGroup; +class G1FromCardCache; class outputStream; class G1HeapRegionRemSet : public CHeapObj { @@ -43,16 +38,11 @@ class G1HeapRegionRemSet : public CHeapObj { // the region that owns this RSet. G1CodeRootSet _code_roots; - // The collection set groups to which the region owning this RSet is assigned. G1CSetCandidateGroup* _cset_group; - G1HeapRegion* _hr; - // Cached value of heap base address. static HeapWord* _heap_base_address; - void clear_fcc(); - G1CardSet* card_set() { assert(has_cset_group(), "pre-condition"); return cset_group()->card_set(); @@ -63,14 +53,14 @@ class G1HeapRegionRemSet : public CHeapObj { return cset_group()->card_set(); } -public: - G1HeapRegionRemSet(G1HeapRegion* hr); - ~G1HeapRegionRemSet(); - - bool cardset_is_empty() const { + bool card_set_is_empty() const { return !has_cset_group() || card_set()->is_empty(); } +public: + G1HeapRegionRemSet(); + ~G1HeapRegionRemSet(); + void install_cset_group(G1CSetCandidateGroup* cset_group) { assert(cset_group != nullptr, "pre-condition"); assert(_cset_group == nullptr, "pre-condition"); @@ -98,14 +88,14 @@ class G1HeapRegionRemSet : public CHeapObj { } bool is_empty() const { - return (code_roots_list_length() == 0) && cardset_is_empty(); + return (code_roots_length() == 0) && card_set_is_empty(); } bool occupancy_less_or_equal_than(size_t occ) const { - return (code_roots_list_length() == 0) && card_set()->occupancy_less_or_equal_to(occ); + return (code_roots_length() == 0) && card_set()->occupancy_less_or_equal_to(occ); } - // Iterate the card based remembered set for merging them into the card table. + // Iterate the cards in this remembered set for merging them into the card table. // The passed closure must be a CardOrRangeVisitor; we use a template parameter // to pass it in to facilitate inlining as much as possible. template @@ -119,7 +109,6 @@ class G1HeapRegionRemSet : public CHeapObj { return card_set()->occupied(); } - static void initialize(MemRegion reserved); inline uintptr_t to_card(OopOrNarrowOopStar from) const; @@ -148,11 +137,10 @@ class G1HeapRegionRemSet : public CHeapObj { inline void set_state_updating(); inline void set_state_complete(); - inline void add_reference(OopOrNarrowOopStar from, uint tid); + inline void add_reference(OopOrNarrowOopStar from, G1FromCardCache& from_card_cache); - // The region is being reclaimed; clear its remset, and any mention of - // entries for this region in other remsets. - void clear(bool only_cardset = false, bool keep_tracked = false); + // Clear the region-specific remset state. + void clear(); void reset_code_root_table_scanner(); void reset_table_scanner(); @@ -162,13 +150,13 @@ class G1HeapRegionRemSet : public CHeapObj { // The actual # of bytes this hr_remset takes up. Also includes the code // root set. size_t mem_size() { - return sizeof(G1HeapRegionRemSet) + code_roots_mem_size(); + return sizeof(G1HeapRegionRemSet) - sizeof(G1CodeRootSet) + code_roots_mem_size(); } // Returns the memory occupancy of all static data structures associated // with remembered sets. static size_t static_mem_size() { - return G1CardSet::static_mem_size() + G1FromCardCache::static_mem_size(); + return G1CardSet::static_mem_size(); } static void print_static_mem_size(outputStream* out); @@ -177,10 +165,9 @@ class G1HeapRegionRemSet : public CHeapObj { inline void print_info(outputStream* st, OopOrNarrowOopStar from); - // Routines for managing the list of code roots that point into - // the heap region that owns this RSet. + // Routines for managing the code roots that point into the heap region + // that owns this RSet. void add_code_root(nmethod* nm); - void remove_code_root(nmethod* nm); void bulk_remove_code_roots(); void prepare_for_adding_code_roots(size_t num_code_roots); @@ -190,13 +177,13 @@ class G1HeapRegionRemSet : public CHeapObj { void clean_code_roots(G1HeapRegion* hr); // Returns the number of elements in _code_roots - size_t code_roots_list_length() const { + size_t code_roots_length() const { return _code_roots.length(); } // Returns true if the code roots contains the given // nmethod. - bool code_roots_list_contains(nmethod* nm) { + bool code_roots_contains(nmethod* nm) { return _code_roots.contains(nm); } @@ -204,15 +191,7 @@ class G1HeapRegionRemSet : public CHeapObj { // consumed by the code roots. size_t code_roots_mem_size(); - static void invalidate_from_card_cache(uint start_idx, size_t num_regions) { - G1FromCardCache::invalidate(start_idx, num_regions); - } - #ifndef PRODUCT - static void print_from_card_cache() { - G1FromCardCache::print(); - } - static void test(); #endif }; diff --git a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.inline.hpp b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.inline.hpp index f621b1318c1e..25b1fbebfff5 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.inline.hpp @@ -22,15 +22,16 @@ * */ -#ifndef SHARE_VM_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP -#define SHARE_VM_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP +#ifndef SHARE_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP +#define SHARE_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP #include "gc/g1/g1HeapRegionRemSet.hpp" #include "gc/g1/g1CardSet.inline.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1HeapRegion.inline.hpp" -#include "utilities/bitMap.inline.hpp" +#include "gc/g1/g1CollectionSetCandidates.hpp" +#include "gc/g1/g1FromCardCache.inline.hpp" +#include "gc/shared/cardTable.hpp" +#include "runtime/safepoint.hpp" void G1HeapRegionRemSet::set_state_untracked() { guarantee(SafepointSynchronize::is_at_safepoint() || !is_tracked(), @@ -38,19 +39,16 @@ void G1HeapRegionRemSet::set_state_untracked() { if (_state == Untracked) { return; } - clear_fcc(); _state = Untracked; } void G1HeapRegionRemSet::set_state_updating() { guarantee(SafepointSynchronize::is_at_safepoint() && !is_tracked(), "Should only set to Updating from Untracked during safepoint but is %s", get_state_str()); - clear_fcc(); _state = Updating; } void G1HeapRegionRemSet::set_state_complete() { - clear_fcc(); _state = Complete; } @@ -123,18 +121,15 @@ uintptr_t G1HeapRegionRemSet::to_card(OopOrNarrowOopStar from) const { return pointer_delta(from, _heap_base_address, 1) >> CardTable::card_shift(); } -void G1HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) { - assert(has_cset_group(), "pre-condition"); +void G1HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, G1FromCardCache& from_card_cache) { + precond(has_cset_group()); + precond(_state != Untracked); - assert(_state != Untracked, "must be"); - - uint cur_idx = _hr->hrm_index(); uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift(); - if (G1FromCardCache::contains_or_replace(tid, cur_idx, from_card)) { + if (from_card_cache.contains_or_add(from_card, cset_group()->group_id())) { // We can't check whether the card is in the remembered set - the card container // may be coarsened just now. - //assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from)); return; } @@ -149,4 +144,4 @@ void G1HeapRegionRemSet::print_info(outputStream* st, OopOrNarrowOopStar from) { card_set()->print_info(st, to_card(from)); } -#endif // SHARE_VM_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP +#endif // SHARE_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp index da8953f5a7df..b477138873a7 100644 --- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp @@ -115,7 +115,7 @@ class G1VerifyCodeRootOopClosure: public OopClosure { G1HeapRegionRemSet* hrrs = hr->rem_set(); // Verify that the code root list for this region // contains the nmethod - if (!hrrs->code_roots_list_contains(_nm)) { + if (!hrrs->code_roots_contains(_nm)) { log_error(gc, verify)("Code root location " PTR_FORMAT " " "from nmethod " PTR_FORMAT " not in strong " "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")", diff --git a/src/hotspot/share/gc/g1/g1OopClosures.hpp b/src/hotspot/share/gc/g1/g1OopClosures.hpp index a61c9d17f70c..b6cbb765280d 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1OOPCLOSURES_HPP #include "classfile/classLoaderData.hpp" +#include "gc/g1/g1FromCardCache.hpp" #include "gc/g1/g1HeapRegionAttr.hpp" #include "memory/iterator.hpp" #include "oops/markWord.hpp" @@ -205,17 +206,16 @@ class G1RootRegionScanClosure : public ClaimMetadataVisitingOopIterateClosure { class G1ConcurrentRefineOopClosure: public BasicOopIterateClosure { G1CollectedHeap* _g1h; - uint _worker_id; + G1FromCardCache _from_card_cache; bool _has_ref_to_cset; bool _has_ref_to_old; public: - G1ConcurrentRefineOopClosure(G1CollectedHeap* g1h, uint worker_id) : + G1ConcurrentRefineOopClosure(G1CollectedHeap* g1h) : _g1h(g1h), - _worker_id(worker_id), + _from_card_cache(), _has_ref_to_cset(false), - _has_ref_to_old(false) { - } + _has_ref_to_old(false) {} bool has_ref_to_cset() const { return _has_ref_to_cset; } bool has_ref_to_old() const { return _has_ref_to_old; } @@ -229,11 +229,14 @@ class G1ConcurrentRefineOopClosure: public BasicOopIterateClosure { class G1RebuildRemSetClosure : public BasicOopIterateClosure { G1CollectedHeap* _g1h; - uint _worker_id; + G1FromCardCache _from_card_cache; public: - G1RebuildRemSetClosure(G1CollectedHeap* g1h, uint worker_id) : _g1h(g1h), _worker_id(worker_id) { - } + G1RebuildRemSetClosure(G1CollectedHeap* g1h) + : _g1h(g1h), + _from_card_cache() {} + + void reset_from_card_cache() { _from_card_cache.reset(); } template void do_oop_work(T* p); virtual void do_oop(oop* p) { do_oop_work(p); } diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index 80fb1be14ddb..aed36f8738fd 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,7 +164,7 @@ inline void G1ConcurrentRefineOopClosure::do_oop_work(T* p) { G1HeapRegion* from = _g1h->heap_region_containing(p); if (from->rem_set()->cset_group() != to_rem_set->cset_group()) { - to_rem_set->add_reference(p, _worker_id); + to_rem_set->add_reference(p, _from_card_cache); _has_ref_to_old = true; } } @@ -291,7 +291,7 @@ template void G1RebuildRemSetClosure::do_oop_work(T* p) { G1HeapRegion* from = _g1h->heap_region_containing(p); if (from->rem_set()->cset_group() != rem_set->cset_group()) { - rem_set->add_reference(p, _worker_id); + rem_set->add_reference(p, _from_card_cache); } } } diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 3a7ff7adc4f1..f120ac320357 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -351,8 +351,7 @@ G1HeapRegionAttr G1ParScanThreadState::next_region_attr(G1HeapRegionAttr const r assert(region_attr.is_young() || region_attr.is_old(), "must be either Young or Old"); if (region_attr.is_young()) { - age = !m.has_displaced_mark_helper() ? m.age() - : m.displaced_mark_helper().age(); + age = m.age(); if (age < _tenuring_threshold) { return region_attr; } diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index fc63a6e212a9..66dd3967e387 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -69,6 +69,7 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _young_gen_sizer(), _free_regions_at_end_of_collection(0), _pending_cards_from_gc(0), + _to_collection_set_cards(0), _collection_set(nullptr), _g1h(nullptr), _phase_times_timer(gc_timer), @@ -1183,7 +1184,7 @@ double G1Policy::predict_merge_scan_time(size_t card_rs_length) const { } double G1Policy::predict_region_code_root_scan_time(G1HeapRegion* hr, bool for_young_only_phase) const { - size_t code_root_length = hr->rem_set()->code_roots_list_length(); + size_t code_root_length = hr->rem_set()->code_roots_length(); return _analytics->predict_code_root_scan_time_ms(code_root_length, for_young_only_phase); diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 149f1da1a8bf..5261d39e715e 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -34,7 +34,6 @@ #include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineSweepTask.hpp" -#include "gc/g1/g1FromCardCache.hpp" #include "gc/g1/g1GCParPhaseTimesTracker.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" @@ -201,8 +200,8 @@ class G1ClearCardTableTask : public G1AbstractSubTask { return AlmostNoWork; } - double num_cards = num_regions << G1HeapRegion::LogCardsPerRegion; - return ceil(num_cards / num_cards_per_worker); + size_t num_cards = (size_t)num_regions << G1HeapRegion::LogCardsPerRegion; + return align_up(num_cards, num_cards_per_worker) / num_cards_per_worker; } virtual ~G1ClearCardTableTask() { @@ -1078,7 +1077,10 @@ class G1MergeHeapRootsTask : public WorkerTask { // remembered sets for this region. // We want to continue collecting remembered set entries for humongous regions // that were not reclaimed. - r->rem_set()->clear(true /* only_cardset */, true /* keep_tracked */); + G1CSetCandidateGroup* group = r->rem_set()->cset_group(); + assert(group != nullptr, "must have a cset group"); + assert(group->length() == 1, "humongous regions cset group must have a single entry"); + group->clear_card_set(); } // Postcondition @@ -1264,8 +1266,7 @@ inline void check_card_ptr(CardTable::CardValue* card_ptr, G1CardTable* ct) { #endif } -G1RemSet::RefineResult G1RemSet::refine_card_concurrently(CardValue* const card_ptr, - const uint worker_id) { +G1RemSet::RefineResult G1RemSet::refine_card_concurrently(CardValue* const card_ptr) { assert(!_g1h->is_stw_gc_active(), "Only call concurrently"); G1CardTable* ct = _g1h->refinement_table(); check_card_ptr(card_ptr, ct); @@ -1295,7 +1296,7 @@ G1RemSet::RefineResult G1RemSet::refine_card_concurrently(CardValue* const card_ MemRegion dirty_region(start, MIN2(scan_limit, end)); assert(!dirty_region.is_empty(), "sanity"); - G1ConcurrentRefineOopClosure conc_refine_cl(_g1h, worker_id); + G1ConcurrentRefineOopClosure conc_refine_cl(_g1h); if (r->oops_on_memregion_seq_iterate_careful(dirty_region, &conc_refine_cl) != nullptr) { if (conc_refine_cl.has_ref_to_cset()) { return HasRefToCSet; diff --git a/src/hotspot/share/gc/g1/g1RemSet.hpp b/src/hotspot/share/gc/g1/g1RemSet.hpp index 4893e0839d00..4b079ae297b3 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.hpp +++ b/src/hotspot/share/gc/g1/g1RemSet.hpp @@ -126,8 +126,7 @@ class G1RemSet: public CHeapObj { // Refine the region corresponding to "card_ptr". Must be called after // being filtered by clean_card_before_refine(), and after proper // fence/synchronization. - RefineResult refine_card_concurrently(CardValue* const card_ptr, - const uint worker_id); + RefineResult refine_card_concurrently(CardValue* const card_ptr); // Print accumulated summary info from the start of the VM. void print_summary_info(); diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index 1c0e15757cc3..00682df647d2 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -269,7 +269,7 @@ class G1HeapRegionStatsClosure: public G1HeapRegionClosure { _max_code_root_mem_sz = code_root_mem_sz; _max_code_root_mem_sz_region = r; } - size_t code_root_elems = hrrs->code_roots_list_length(); + size_t code_root_elems = hrrs->code_roots_length(); G1PerRegionTypeRemSetCounters* current = nullptr; if (r->is_free()) { @@ -392,7 +392,7 @@ class G1HeapRegionStatsClosure: public G1HeapRegionClosure { HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), byte_size_in_proper_unit(max_code_root_rem_set->code_roots_mem_size()), proper_unit_for_byte_size(max_code_root_rem_set->code_roots_mem_size()), - max_code_root_rem_set->code_roots_list_length()); + max_code_root_rem_set->code_roots_length()); } }; diff --git a/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp b/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp index 94f5466b8e0f..587ef2b6a12a 100644 --- a/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp @@ -102,11 +102,17 @@ void G1RemSetTrackingPolicy::update_after_rebuild(G1HeapRegion* r) { // cycle as e.g. remembered set entries will always be added. if (r->is_starts_humongous() && !g1h->is_potential_eager_reclaim_candidate(r)) { // Handle HC regions with the HS region. + G1CSetCandidateGroup* group = r->rem_set()->cset_group(); + + assert(group != nullptr, "humongous start must have a cset group"); + assert(group->length() == 1, "humongous group must have only one region"); + + group->clear_card_set(); g1h->humongous_obj_regions_iterate(r, [&] (G1HeapRegion* r) { assert(!r->is_continues_humongous() || r->rem_set()->is_empty(), "Continues humongous region %u remset should be empty", r->hrm_index()); - r->rem_set()->clear(true /* only_cardset */); + r->rem_set()->set_state_untracked(); }); } diff --git a/src/hotspot/share/gc/g1/g1ReviseNumYoungRegionsTask.cpp b/src/hotspot/share/gc/g1/g1ReviseNumYoungRegionsTask.cpp index 71c8d7bf772c..22cee3bb457f 100644 --- a/src/hotspot/share/gc/g1/g1ReviseNumYoungRegionsTask.cpp +++ b/src/hotspot/share/gc/g1/g1ReviseNumYoungRegionsTask.cpp @@ -55,7 +55,7 @@ class G1ReviseNumYoungRegionsTask::RemSetSamplingClosure : public G1HeapRegionCl bool do_heap_region(G1HeapRegion* r) override { G1HeapRegionRemSet* rem_set = r->rem_set(); - _sampled_code_root_rs_length += rem_set->code_roots_list_length(); + _sampled_code_root_rs_length += rem_set->code_roots_length(); return false; } diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 359ed4586c17..f8137a162016 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -436,7 +436,7 @@ class G1PrepareEvacuationTask : public WorkerTask { cast_to_oop(hr->bottom())->size() * HeapWordSize, p2i(hr->bottom()), hr->rem_set()->occupied(), - hr->rem_set()->code_roots_list_length(), + hr->rem_set()->code_roots_length(), _g1h->concurrent_mark()->mark_bitmap()->is_marked(hr->bottom()), hr->pinned_count(), _g1h->is_humongous_reclaim_candidate(index), diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index 1d8e358c72b7..2f7fb7cd970e 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,8 +249,7 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o, size_t new_obj_size = o->size_given_klass(klass); // Find the objects age, MT safe. - uint age = (test_mark.has_displaced_mark_helper() /* o->has_displaced_mark() */) ? - test_mark.displaced_mark_helper().age() : test_mark.age(); + uint age = test_mark.age(); if (!promote_immediately) { // Try allocating obj in to-space (unless too old) diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp index a0876a8842c9..8ff93029e832 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp @@ -316,8 +316,6 @@ class BarrierSetC2: public CHeapObj { Node*& fast_oop_ctrl, Node*& fast_oop_rawmem, intx prefetch_lines) const; - virtual Node* ideal_node(PhaseGVN* phase, Node* n, bool can_reshape) const { return nullptr; } - // These are general helper methods used by C2 enum ArrayCopyPhase { Parsing, @@ -328,19 +326,9 @@ class BarrierSetC2: public CHeapObj { virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const { return false; } virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const; - // Support for GC barriers emitted during parsing - virtual bool has_load_barrier_nodes() const { return false; } - virtual bool is_gc_pre_barrier_node(Node* node) const { return false; } - virtual bool is_gc_barrier_node(Node* node) const { return false; } - virtual Node* step_over_gc_barrier(Node* c) const { return c; } - // Support for macro expanded GC barriers - virtual void register_potential_barrier_node(Node* node) const { } - virtual void unregister_potential_barrier_node(Node* node) const { } virtual void eliminate_gc_barrier(PhaseIterGVN* igvn, Node* node) const { } virtual void eliminate_gc_barrier_data(Node* node) const { } - virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const {} - virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const {} // Allow barrier sets to have shared state that is preserved across a compilation unit. // This could for example comprise macro nodes to be expanded during macro expansion. @@ -349,9 +337,6 @@ class BarrierSetC2: public CHeapObj { // unit state to be expanded later, then now is the time to do so. virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const { return false; } virtual void final_refinement(Compile* C) const { } - virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const { return false; } - virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return false; } - virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return false; } // Estimated size of the node barrier in number of C2 Ideal nodes. // This is used to guide heuristics in C2, e.g. whether to unroll a loop. virtual uint estimated_barrier_size(const Node* node) const { return 0; } @@ -368,15 +353,6 @@ class BarrierSetC2: public CHeapObj { virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const {} #endif - virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode, Unique_Node_List& dead_nodes) const { return false; } - - virtual bool escape_add_to_con_graph(ConnectionGraph* conn_graph, PhaseGVN* gvn, Unique_Node_List* delayed_worklist, Node* n, uint opcode) const { return false; } - virtual bool escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN* gvn, Node* n, uint opcode) const { return false; } - virtual bool escape_has_out_with_unsafe_object(Node* n) const { return false; } - - virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const { return false; }; - virtual bool matcher_is_store_load_barrier(Node* x, uint xop) const { return false; } - // Whether the given phi node joins OOPs from fast and slow allocation paths. static bool is_allocation(const Node* node); // Elide GC barriers from a Mach node according to elide_dominated_barriers(). diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 336f4bd59a12..2eeee2b0cac6 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -46,6 +46,8 @@ #include "gc/z/z_globals.hpp" #endif +constexpr uint MaxGCCardSizeInBytes = NOT_LP64(512) LP64_ONLY(1024); + #define GC_FLAGS(develop, \ develop_pd, \ product, \ @@ -523,7 +525,7 @@ \ product(uint, GCCardSizeInBytes, 512, \ "Card table entry size (in bytes) for card based collectors") \ - range(128, NOT_LP64(512) LP64_ONLY(1024)) \ + range(128, MaxGCCardSizeInBytes) \ constraint(GCCardSizeInBytesConstraintFunc,AtParse) // end of GC_FLAGS diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 1bac056a2253..298c756ef2b3 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -40,10 +40,6 @@ #include "opto/rootnode.hpp" #include "opto/runtime.hpp" -ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2() { - return reinterpret_cast(BarrierSet::barrier_set()->barrier_set_c2()); -} - ShenandoahBarrierSetC2State::ShenandoahBarrierSetC2State(Arena* comp_arena) : BarrierSetC2State(comp_arena), _stubs(new (comp_arena) GrowableArray(comp_arena, 8, 0, nullptr)), @@ -667,10 +663,6 @@ void* ShenandoahBarrierSetC2::create_barrier_state(Arena* comp_arena) const { return new(comp_arena) ShenandoahBarrierSetC2State(comp_arena); } -ShenandoahBarrierSetC2State* ShenandoahBarrierSetC2::state() const { - return reinterpret_cast(Compile::current()->barrier_set_state()); -} - void ShenandoahBarrierSetC2::print_barrier_data(outputStream* os, uint8_t data) { os->print(" Node barriers: "); if ((data & ShenandoahBitStrong) != 0) { @@ -888,7 +880,7 @@ void ShenandoahBarrierSetC2::emit_stubs(CodeBuffer& cb) const { skipped_after, skipped_before, skipped_after - skipped_before); #endif - masm.flush(); + // Code will be copied. No ICache sync required. } void ShenandoahBarrierStubC2::register_stub(ShenandoahBarrierStubC2* stub) { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp index 097e28a562ef..065c746d93ce 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp @@ -110,10 +110,6 @@ class ShenandoahBarrierSetC2 : public BarrierSetC2 { virtual Node* atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* val_type) const; public: - static ShenandoahBarrierSetC2* bsc2(); - - ShenandoahBarrierSetC2State* state() const; - // This is the entry-point for the backend to perform accesses through the Access API. virtual void clone(GraphKit* kit, Node* src_base, Node* dst_base, Node* size, bool is_array) const; virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index dd259497d341..55a582cd54c2 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -228,7 +228,7 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { PROPERFMTARGS(available), PROPERFMTARGS(capacity)); if (_start_gc_is_pending) { - log_trigger("GC start is already pending"); + log_info(gc, ergo)("GC start is already pending"); return true; } @@ -263,7 +263,7 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { bool ShenandoahAdaptiveHeuristics::trigger_min_free_threshold(size_t available, size_t capacity) { const size_t min_threshold = min_free_threshold(capacity); if (available < min_threshold) { - log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", + log_trigger("Occupancy. " PROPERFMT " free, below " PROPERFMT " threshold", PROPERFMTARGS(available), PROPERFMTARGS(min_threshold)); accept_trigger_with_type(OTHER); return true; @@ -276,8 +276,9 @@ bool ShenandoahAdaptiveHeuristics::trigger_learning(size_t available, size_t cap if (_gc_times_learned < ShenandoahLearningSteps) { const size_t init_threshold = capacity / 100 * ShenandoahInitFreeThreshold; if (available < init_threshold) { - log_trigger("Learning %zu of %zu. Free (" PROPERFMT ") is below initial threshold (" PROPERFMT ")", - _gc_times_learned + 1, ShenandoahLearningSteps, PROPERFMTARGS(available), PROPERFMTARGS(init_threshold)); + log_trigger("Learning. Step %zu of %zu, " PROPERFMT " free, below " PROPERFMT " threshold", + _gc_times_learned + 1, ShenandoahLearningSteps, + PROPERFMTARGS(available), PROPERFMTARGS(init_threshold)); accept_trigger_with_type(OTHER); return true; } @@ -287,10 +288,11 @@ bool ShenandoahAdaptiveHeuristics::trigger_learning(size_t available, size_t cap bool ShenandoahAdaptiveHeuristics::trigger_average_allocation_rate(const ShenandoahAnticipatedConsumption& rate, const size_t allocatable_bytes) { if (rate.baseline_consumption() > allocatable_bytes) { - log_trigger("Anticipated GC duration (%.2f ms) is above the time for average allocation rate (" PROPERFMT_F "/s)" - " to deplete free headroom (" PROPERFMT ") (margin of error = %.2f)", - rate.duration_seconds() * 1000, - PROPERFMT_F_ARGS(rate.baseline_rate()), PROPERFMTARGS(allocatable_bytes), _margin_of_error_sd); + const ShenandoahSignedSize baseline_rate = ShenandoahSignedSize::get(rate.baseline_rate()); + log_trigger("Allocation Rate. %.2fms GC predicted, " PROPERFMT " free, " + PROPERFMT_F "/s average allocation rate", + rate.duration_seconds() * 1000, PROPERFMTARGS(allocatable_bytes), + PROPERFMTARGS_SIGNED(baseline_rate)); accept_trigger_with_type(RATE); return true; } @@ -383,10 +385,10 @@ bool ShenandoahAdaptiveHeuristics::trigger_accelerating_allocation_rate(const Sh if (rate.momentary_consumption() > allocatable_bytes) { const ShenandoahSignedSize momentary_rate = ShenandoahSignedSize::get(rate.momentary_rate()); assert(rate.accelerated_consumption() == 0, "Momentary trigger is meant to exclude acceleration trigger"); - log_trigger("Momentary spike consumption (" PROPERFMT ") exceeds free headroom (" PROPERFMT ") at " - "current rate (" PROPERFMT_F "/s) for anticipated GC duration (%.2f ms)", - PROPERFMTARGS(rate.momentary_consumption()), PROPERFMTARGS(allocatable_bytes), - PROPERFMTARGS_SIGNED(momentary_rate), rate.duration_seconds() * 1000); + log_trigger("Allocation Rate. %.2fms GC predicted, " PROPERFMT " free, " + PROPERFMT_F "/s momentary allocation rate", + rate.duration_seconds() * 1000, PROPERFMTARGS(allocatable_bytes), + PROPERFMTARGS_SIGNED(momentary_rate)); accept_trigger_with_type(RATE); return true; } @@ -395,10 +397,10 @@ bool ShenandoahAdaptiveHeuristics::trigger_accelerating_allocation_rate(const Sh const ShenandoahSignedSize predicted_rate = ShenandoahSignedSize::get(rate.predicted_rate()); const ShenandoahSignedSize acceleration = ShenandoahSignedSize::get(rate.acceleration()); assert(rate.momentary_consumption() == 0, "Acceleration trigger is meant to exclude momentary trigger"); - log_trigger("Accelerated consumption (" PROPERFMT ") exceeds free headroom (" PROPERFMT ") at " - "current rate (" PROPERFMT_F "/s) with acceleration (" PROPERFMT_F "/s/s) for anticipated GC duration (%.2f ms)", - PROPERFMTARGS(rate.accelerated_consumption()), PROPERFMTARGS(allocatable_bytes), - PROPERFMTARGS_SIGNED(predicted_rate), PROPERFMTARGS_SIGNED(acceleration), rate.duration_seconds() * 1000); + log_trigger("Allocation Rate. %.2fms GC predicted, " PROPERFMT " free, " + PROPERFMT_F "/s predicted allocation rate, " PROPERFMT_F "/s^2 acceleration", + rate.duration_seconds() * 1000, PROPERFMTARGS(allocatable_bytes), + PROPERFMTARGS_SIGNED(predicted_rate), PROPERFMTARGS_SIGNED(acceleration)); accept_trigger_with_type(RATE); return true; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp index 26a2363d4d50..a11820e5a809 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,14 +60,14 @@ bool ShenandoahCompactHeuristics::should_start_gc() { const size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold; if (available < min_threshold) { - log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", + log_trigger("Occupancy. " PROPERFMT " free, below " PROPERFMT " threshold", PROPERFMTARGS(available), PROPERFMTARGS(min_threshold)); accept_trigger(); return true; } if (bytes_allocated > threshold_bytes_allocated) { - log_trigger("Allocated since last cycle started (" PROPERFMT ") is larger than allocation threshold (" PROPERFMT ")", + log_trigger("Allocation. " PROPERFMT " allocated, above " PROPERFMT " threshold", PROPERFMTARGS(bytes_allocated), PROPERFMTARGS(threshold_bytes_allocated)); accept_trigger(); return true; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index dbc795651f22..31f32836ceb3 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahInPlacePromoter.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" @@ -107,9 +108,14 @@ size_t ShenandoahGenerationalHeuristics::prepare_regions_for_promotion(Shenandoa assert_no_in_place_promotions(); size_t candidates = 0; for (size_t i = 0, num_regions = heap->num_regions(); i < num_regions; i++) { + if (!heap->is_region_young(i)) { + // Skip regions that aren't young + continue; + } + ShenandoahHeapRegion* const r = heap->get_region(i); - if (r->is_empty() || !r->has_live() || !r->is_young()) { - // skip over regions that aren't young with some live data + if (r->is_empty() || !r->has_live()) { + // Skip over regions that don't have live data continue; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index a0aec3c70a29..d0a5d0e0cc10 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2018, 2026, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahAllocRate.inline.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" @@ -100,12 +101,11 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec size_t free_regions = 0; for (size_t i = 0; i < num_regions; i++) { - ShenandoahHeapRegion* region = heap->get_region(i); - - if (!_space_info->contains(region)) { + if (!_space_info->contains(heap->region_affiliation(i))) { continue; } + ShenandoahHeapRegion* region = heap->get_region(i); size_t garbage = region->garbage(); total_garbage += garbage; @@ -189,7 +189,7 @@ void ShenandoahHeuristics::record_cycle_end() { bool ShenandoahHeuristics::should_start_gc() { if (_start_gc_is_pending) { - log_trigger("GC start is already pending"); + log_info(gc, ergo)("GC start is already pending"); return true; } // Perform GC to cleanup metaspace @@ -203,8 +203,8 @@ bool ShenandoahHeuristics::should_start_gc() { if (_guaranteed_gc_interval > 0) { double last_time_ms = (os::elapsedTime() - _last_cycle_end) * 1000; if (last_time_ms > _guaranteed_gc_interval) { - log_trigger("Time since last GC (%.0f ms) is larger than guaranteed interval (%zu ms)", - last_time_ms, _guaranteed_gc_interval); + log_trigger("Guaranteed Interval. %.0f ms since last GC, above %zu ms guaranteed interval", + last_time_ms, _guaranteed_gc_interval); accept_trigger(); return true; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 44bc683cbd6c..1b956b6994a3 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" @@ -413,11 +414,11 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { size_t live_data = 0; RegionData* candidates = _region_data; for (size_t i = 0; i < num_regions; i++) { - ShenandoahHeapRegion* region = heap->get_region(i); - if (!region->is_old()) { + if (!heap->is_region_old(i)) { continue; } + ShenandoahHeapRegion* region = heap->get_region(i); size_t garbage = region->garbage(); size_t live_bytes = region->get_live_data_bytes(); if (!region->was_promoted_in_place()) { @@ -724,13 +725,13 @@ bool ShenandoahOldHeuristics::should_resume_old_cycle() { // If we are preparing to mark old, or if we are already marking old, then try to continue that work. if (_old_generation->is_concurrent_mark_in_progress()) { assert(_old_generation->state() == ShenandoahOldGeneration::MARKING, "Unexpected old gen state: %s", _old_generation->state_name()); - log_trigger("Resume marking old"); + log_trigger("Resume Marking"); return true; } if (_old_generation->is_preparing_for_mark()) { assert(_old_generation->state() == ShenandoahOldGeneration::FILLING, "Unexpected old gen state: %s", _old_generation->state_name()); - log_trigger("Resume preparing to mark old"); + log_trigger("Resume Prepare Marking"); return true; } @@ -750,7 +751,7 @@ bool ShenandoahOldHeuristics::should_start_gc() { const size_t old_gen_capacity = _old_generation->max_capacity(); const size_t heap_capacity = heap->capacity(); const double percent = percent_of(old_gen_capacity, heap_capacity); - log_trigger("Expansion failure, current size: %zu%s which is %.1f%% of total heap size", + log_trigger("Handle Expansion Failure. %zu%s (%.1f%%) old generation", byte_size_in_proper_unit(old_gen_capacity), proper_unit_for_byte_size(old_gen_capacity), percent); adjust_old_garbage_threshold(); return true; @@ -770,9 +771,7 @@ bool ShenandoahOldHeuristics::should_start_gc() { const size_t span_of_old_regions = (last_old_region >= first_old_region)? last_old_region + 1 - first_old_region: 0; const size_t fragmented_free = used_regions_size - used; - log_trigger("Old has become fragmented: " - "%zu%s available bytes spread between range spanned from " - "%zu to %zu (%zu), density: %.1f%%", + log_trigger("Fragmentation. %zu%s available in old, [%zu, %zu] (%zu) regions, density: %.1f%%", byte_size_in_proper_unit(fragmented_free), proper_unit_for_byte_size(fragmented_free), first_old_region, last_old_region, span_of_old_regions, density * 100); adjust_old_garbage_threshold(); @@ -800,8 +799,7 @@ bool ShenandoahOldHeuristics::should_start_gc() { } else if (current_usage > trigger_threshold) { const size_t live_at_previous_old = _old_generation->get_live_bytes_at_last_mark(); const double percent_growth = percent_of(current_usage - live_at_previous_old, live_at_previous_old); - log_trigger("Old has overgrown, live at end of previous OLD marking: " - "%zu%s, current usage: %zu%s, percent growth: %.1f%%", + log_trigger("Occupancy. %zu%s live at old mark end, %zu%s used, %.1f%% growth", byte_size_in_proper_unit(live_at_previous_old), proper_unit_for_byte_size(live_at_previous_old), byte_size_in_proper_unit(current_usage), proper_unit_for_byte_size(current_usage), percent_growth); adjust_old_garbage_threshold(); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp index 85c5d9fb2fb2..68e297a8273a 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHSPACEINFO_HPP #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHSPACEINFO_HPP +#include "gc/shenandoah/shenandoahAffiliation.hpp" #include "utilities/globalDefinitions.hpp" class ShenandoahHeapRegion; @@ -46,6 +47,7 @@ class ShenandoahSpaceInfo { // Return true if this region belongs to this space. virtual bool contains(ShenandoahHeapRegion* region) const = 0; + virtual bool contains(ShenandoahAffiliation affiliation) const = 0; }; #endif //SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHSPACEINFO_HPP diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp index 98d679f86d9c..0ceab0460cfd 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,8 +46,8 @@ bool ShenandoahStaticHeuristics::should_start_gc() { size_t threshold_available = capacity / 100 * ShenandoahMinFreeThreshold; if (available < threshold_available) { - log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", - PROPERFMTARGS(available), PROPERFMTARGS(threshold_available)); + log_trigger("Occupancy. " PROPERFMT " free, below " PROPERFMT " threshold", + PROPERFMTARGS(available), PROPERFMTARGS(threshold_available)); accept_trigger(); return true; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index 280076377594..49be36aaf949 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -138,7 +138,7 @@ bool ShenandoahYoungHeuristics::trigger_expedite_promotions(ShenandoahGeneration if (promo_potential > promo_expedite_threshold) { // Detect unsigned arithmetic underflow assert(promo_potential < heap->capacity(), "Sanity"); - log_trigger("Expedite promotion of " PROPERFMT, PROPERFMTARGS(promo_potential)); + log_trigger("Expedite Promotion. " PROPERFMT " promotion potential", PROPERFMTARGS(promo_potential)); accept_trigger(); return true; } @@ -152,7 +152,7 @@ bool ShenandoahYoungHeuristics::trigger_expedite_mixed(ShenandoahGenerationalHea // If concurrent weak root processing is in progress, it means the old cycle has chosen mixed collection // candidates, but has not completed. There is no point in trying to start the young cycle before the old // cycle completes. - log_trigger("Expedite mixed evacuation of %zu regions", mixed_candidates); + log_trigger("Expedite Mixed. %zu region candidates for mixed evacuation", mixed_candidates); accept_trigger(); return true; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp index 8fa497802fde..3c23dd0bf233 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ #include "gc/shenandoah/mode/shenandoahGenerationalMode.hpp" -#include "gc/shenandoah/shenandoahAgeCensus.hpp" +#include "gc/shenandoah/shenandoahAgeCensus.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" ShenandoahAgeCensus::ShenandoahAgeCensus() @@ -82,38 +82,6 @@ ShenandoahAgeCensus::~ShenandoahAgeCensus() { } } -CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, uint region_youth, size_t size, uint worker_id) {) -NO_CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, size_t size, uint worker_id) {) - if (obj_age <= markWord::max_age) { - assert(obj_age < MAX_COHORTS && region_age < MAX_COHORTS, "Should have been tenured"); -#ifdef SHENANDOAH_CENSUS_NOISE - // Region ageing is stochastic and non-monotonic; this vitiates mortality - // demographics in ways that might defeat our algorithms. Marking may be a - // time when we might be able to correct this, but we currently do not do - // this. Like skipped statistics further below, we want to track the - // impact of this noise to see if this may be worthwhile. JDK-. - uint age = obj_age; - if (region_age > 0) { - add_aged(size, worker_id); // this tracking is coarse for now - age += region_age; - if (age >= MAX_COHORTS) { - age = (uint)(MAX_COHORTS - 1); // clamp - add_clamped(size, worker_id); - } - } - if (region_youth > 0) { // track object volume with retrograde age - add_young(size, worker_id); - } -#else // SHENANDOAH_CENSUS_NOISE - uint age = MIN2(obj_age + region_age, (uint)(MAX_COHORTS - 1)); // clamp -#endif // SHENANDOAH_CENSUS_NOISE - get_local_age_table(worker_id)->add(age, size); - } else { - // update skipped statistics - CENSUS_NOISE(add_skipped(size, worker_id);) - } -} - #ifdef SHENANDOAH_CENSUS_NOISE void ShenandoahAgeCensus::add_skipped(size_t size, uint worker_id) { _local_noise[worker_id].skipped += size; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp index 8cc8e31cf291..2d79eb559609 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp @@ -205,8 +205,8 @@ class ShenandoahAgeCensus: public CHeapObj { // Update the local age table for worker_id by size for // given obj_age, region_age, and region_youth - CENSUS_NOISE(void add(uint obj_age, uint region_age, uint region_youth, size_t size, uint worker_id);) - NO_CENSUS_NOISE(void add(uint obj_age, uint region_age, size_t size, uint worker_id);) + CENSUS_NOISE(inline void add(uint obj_age, uint region_age, uint region_youth, size_t size, uint worker_id);) + NO_CENSUS_NOISE(inline void add(uint obj_age, uint region_age, size_t size, uint worker_id);) #ifdef SHENANDOAH_CENSUS_NOISE // Update the local skip table for worker_id by size diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.inline.hpp new file mode 100644 index 000000000000..299b9a3f8b7a --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.inline.hpp @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHAGECENSUS_INLINE_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHAGECENSUS_INLINE_HPP + +#include "gc/shenandoah/shenandoahAgeCensus.hpp" + +CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, uint region_youth, size_t size, uint worker_id) {) +NO_CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, size_t size, uint worker_id) {) + if (obj_age <= markWord::max_age) { + assert(obj_age < MAX_COHORTS && region_age < MAX_COHORTS, "Should have been tenured"); +#ifdef SHENANDOAH_CENSUS_NOISE + // Region ageing is stochastic and non-monotonic; this vitiates mortality + // demographics in ways that might defeat our algorithms. Marking may be a + // time when we might be able to correct this, but we currently do not do + // this. Like skipped statistics further below, we want to track the + // impact of this noise to see if this may be worthwhile. JDK-. + uint age = obj_age; + if (region_age > 0) { + add_aged(size, worker_id); // this tracking is coarse for now + age += region_age; + if (age >= MAX_COHORTS) { + age = (uint)(MAX_COHORTS - 1); // clamp + add_clamped(size, worker_id); + } + } + if (region_youth > 0) { // track object volume with retrograde age + add_young(size, worker_id); + } +#else // SHENANDOAH_CENSUS_NOISE + uint age = MIN2(obj_age + region_age, (uint)(MAX_COHORTS - 1)); // clamp +#endif // SHENANDOAH_CENSUS_NOISE + get_local_age_table(worker_id)->add(age, size); + } else { + // update skipped statistics + CENSUS_NOISE(add_skipped(size, worker_id);) + } +} + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHAGECENSUS_INLINE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 1e839fab6554..107f126b44d5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -29,9 +29,14 @@ #include "gc/shenandoah/shenandoahBarrierSetStackChunk.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" +#include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" +#include "gc/shenandoah/shenandoahForwarding.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahStackWatermark.hpp" +#include "memory/iterator.inline.hpp" +#include "oops/compressedOops.inline.hpp" #ifdef COMPILER1 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #endif @@ -94,8 +99,7 @@ bool ShenandoahBarrierSet::need_satb_barrier(DecoratorSet decorators, BasicType bool ShenandoahBarrierSet::need_card_barrier(DecoratorSet decorators, BasicType type) { if (!ShenandoahCardBarrier) return false; if (!is_reference_type(type)) return false; - bool in_heap = (decorators & IN_HEAP) != 0; - return in_heap; + return is_heap_access(decorators); } void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) { @@ -181,8 +185,51 @@ void ShenandoahBarrierSet::on_thread_detach(Thread *thread) { } } -void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) { - assert(ShenandoahCardBarrier, "Should have been checked by caller"); +void ShenandoahBarrierSet::keepalive_barrier_slow(oop obj, Filter filter) { + if (!ShenandoahSATBBarrier) { + return; + } + assert(obj != nullptr, "Filtered by caller"); + assert(_heap->is_concurrent_mark_in_progress(), "Filtered by caller"); + + // Filter marked objects before hitting the SATB queues. The same predicate would + // be used by SATBMQ::filter to eliminate already marked objects downstream, but + // filtering here helps to avoid wasteful SATB queueing work to begin with. + if (((filter & FILTER_MARKED) != 0) && !_heap->requires_marking(obj)) { + return; + } + + shenandoah_assert_correct(nullptr, obj); + assert(_satb_mark_queue_set.is_active(), "only get here when SATB active"); + + SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(Thread::current()); + _satb_mark_queue_set.enqueue_known_active(queue, obj); +} + +template +oop ShenandoahBarrierSet::load_reference_barrier_slow(oop obj, T* load_addr) { + if (!ShenandoahLoadRefBarrier) { + return obj; + } + assert(_heap->has_forwarded_objects(), "Filtered by caller"); + assert(_heap->in_collection_set(obj), "Filtered by caller"); + oop fwd = ShenandoahForwarding::get_forwardee(obj); + if (obj == fwd && _heap->is_evacuation_in_progress()) { + Thread* t = Thread::current(); + fwd = _heap->evacuate_object(obj, t); + } + if (load_addr != nullptr && fwd != obj) { + // Since we are here and we know the load address, update the reference. + ShenandoahHeap::atomic_update_oop(fwd, load_addr, obj); + } + return fwd; +} + +template oop ShenandoahBarrierSet::load_reference_barrier_slow(oop obj, oop* load_addr); +template oop ShenandoahBarrierSet::load_reference_barrier_slow(oop obj, narrowOop* load_addr); + +void ShenandoahBarrierSet::card_barrier_array_slow(HeapWord* start, size_t count) { + assert(ShenandoahCardBarrier, "Filtered by caller"); HeapWord* end = (HeapWord*)((char*) start + (count * heapOopSize)); // In the case of compressed oops, start and end may potentially be misaligned; @@ -199,3 +246,164 @@ void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) { _heap->old_generation()->card_scan()->mark_range_as_dirty(aligned_start, (aligned_end - aligned_start)); } +// Clone barrier support +template +class ShenandoahUpdateEvacForCloneOopClosure : public BasicOopIterateClosure { +private: + ShenandoahHeap* const _heap; + const ShenandoahCollectionSet* const _cset; + Thread* const _thread; + + template + inline void do_oop_work(T* p) { + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); + if (_cset->is_in(obj)) { + oop fwd = ShenandoahForwarding::get_forwardee(obj); + if (EVAC && obj == fwd) { + fwd = _heap->evacuate_object(obj, _thread); + } + shenandoah_assert_forwarded_except(p, obj, _heap->cancelled_gc()); + ShenandoahHeap::atomic_update_oop(fwd, p, o); + obj = fwd; + } + } + } + +public: + ShenandoahUpdateEvacForCloneOopClosure() : + _heap(ShenandoahHeap::heap()), + _cset(_heap->collection_set()), + _thread(Thread::current()) {} + + virtual void do_oop(oop* p) { do_oop_work(p); } + virtual void do_oop(narrowOop* p) { do_oop_work(p); } +}; + +void ShenandoahBarrierSet::clone_evacuation(oop obj) { + if (!ShenandoahCloneBarrier) { + return; + } + if (!need_bulk_update(cast_from_oop(obj))) { + return; + } + + ShenandoahUpdateEvacForCloneOopClosure cl; + obj->oop_iterate(&cl); +} + +void ShenandoahBarrierSet::clone_update(oop obj) { + if (!ShenandoahCloneBarrier) { + return; + } + if (!need_bulk_update(cast_from_oop(obj))) { + return; + } + + ShenandoahUpdateEvacForCloneOopClosure cl; + obj->oop_iterate(&cl); +} + +template +bool ShenandoahBarrierSet::is_above_tams(const ShenandoahMarkingContext* ctx, T* dst) const { + // TAMS for an old region is unreliable during a young-only mark, so overwritten pointers in old dst arrays must + // be enqueued to preserve old->young referents copied in and overwritten after init mark. See JDK-8373116. + return ctx->allocated_after_mark_start(reinterpret_cast(dst)) + && !(IS_GENERATIONAL + && _heap->heap_region_containing(dst)->is_old() + && _heap->is_concurrent_young_mark_in_progress()); +} + +inline bool ShenandoahBarrierSet::need_bulk_update(HeapWord* ary) const { + return ary < _heap->heap_region_containing(ary)->get_update_watermark(); +} + +template +void ShenandoahBarrierSet::arraycopy_marking(T* dst, size_t count) { + assert(_heap->is_concurrent_mark_in_progress(), "only during marking"); + if (!ShenandoahSATBBarrier) { + return; + } + + const ShenandoahMarkingContext* ctx = _heap->marking_context(); + // Everything allocated above TAMS is alive and doesn't need the barrier to keep it that way + if (is_above_tams(ctx, dst)) { + return; + } + + assert(!_heap->has_forwarded_objects() || _heap->is_concurrent_old_mark_in_progress(), "Forwarded object status is sane"); + Thread* thread = Thread::current(); + SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread); + T* end = dst + count; + for (T* elem_ptr = dst; elem_ptr < end; ++elem_ptr) { + T o = RawAccess<>::oop_load(elem_ptr); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); + if (!ctx->is_marked_strong(obj)) { + _satb_mark_queue_set.enqueue_known_active(queue, obj); + } + } + } +} + +template void ShenandoahBarrierSet::arraycopy_marking(oop* dst, size_t count); +template void ShenandoahBarrierSet::arraycopy_marking(narrowOop* dst, size_t count); +template void ShenandoahBarrierSet::arraycopy_marking(oop* dst, size_t count); +template void ShenandoahBarrierSet::arraycopy_marking(narrowOop* dst, size_t count); + +template +void ShenandoahBarrierSet::arraycopy_evacuation(T* src, size_t count) { + assert(_heap->is_evacuation_in_progress(), "only during evacuation"); + if (!need_bulk_update(reinterpret_cast(src))) { + return; + } + + assert(_heap->has_forwarded_objects(), "Forwarded object status is sane"); + Thread* thread = Thread::current(); + const ShenandoahCollectionSet* const cset = _heap->collection_set(); + T* end = src + count; + for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) { + T o = RawAccess<>::oop_load(elem_ptr); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); + if (cset->is_in(obj)) { + oop fwd = ShenandoahForwarding::get_forwardee(obj); + if (obj == fwd) { + fwd = _heap->evacuate_object(obj, thread); + } + shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); + ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); + } + } + } +} + +template void ShenandoahBarrierSet::arraycopy_evacuation(oop* src, size_t count); +template void ShenandoahBarrierSet::arraycopy_evacuation(narrowOop* src, size_t count); + +template +void ShenandoahBarrierSet::arraycopy_update(T* src, size_t count) { + assert(_heap->is_update_refs_in_progress(), "only during update-refs"); + if (!need_bulk_update(reinterpret_cast(src))) { + return; + } + + assert(_heap->has_forwarded_objects(), "Forwarded object status is sane"); + const ShenandoahCollectionSet* const cset = _heap->collection_set(); + T* end = src + count; + for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) { + T o = RawAccess<>::oop_load(elem_ptr); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); + if (cset->is_in(obj)) { + oop fwd = ShenandoahForwarding::get_forwardee(obj); + shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); + ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); + } + } + } +} + +template void ShenandoahBarrierSet::arraycopy_update(oop* src, size_t count); +template void ShenandoahBarrierSet::arraycopy_update(narrowOop* src, size_t count); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp index 4ae1f03a08da..83f0d42e2781 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -80,10 +80,11 @@ class ShenandoahBarrierSet: public BarrierSet { return (decorators & IN_NATIVE) != 0; } - void print_on(outputStream* st) const override; + static bool is_heap_access(DecoratorSet decorators) { + return (decorators & IN_HEAP) != 0; + } - template - inline void arraycopy_barrier(T* src, T* dst, size_t count, bool dest_uninit); + void print_on(outputStream* st) const override; // Support for optimizing compilers to call the barrier set on slow path allocations // that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks to take any @@ -94,49 +95,68 @@ class ShenandoahBarrierSet: public BarrierSet { void on_thread_attach(Thread* thread) override; void on_thread_detach(Thread* thread) override; - template - inline void satb_barrier(T* field); - inline void satb_enqueue(oop value); - - inline void keep_alive_if_weak(DecoratorSet decorators, oop value); + enum Filter { + FILTER_NONE = 0, + FILTER_WEAK = (1 << 0), + FILTER_MARKED = (1 << 1), + FILTER_WEAK_AND_MARKED = FILTER_WEAK | FILTER_MARKED, + }; - inline void enqueue(oop obj, bool filter = true); + template + inline oop oop_load_post(DecoratorSet decorators, oop value, T* addr); - inline oop load_reference_barrier(oop obj); + template + inline void oop_store_pre(DecoratorSet decorators, T* addr, oop new_value); - template - inline oop load_reference_barrier_mutator(oop obj, T* load_addr); + template + inline void oop_cmpxchg_pre(DecoratorSet decorators, T* addr, oop compare_value, oop new_value); - template - inline oop load_reference_barrier(DecoratorSet decorators, oop obj, T* load_addr); + template + inline void oop_xchg_pre(DecoratorSet decorators, T* addr, oop new_value); template - inline oop oop_cmpxchg(DecoratorSet decorators, T* addr, oop compare_value, oop new_value); + inline void oop_store_post(DecoratorSet decorators, T* addr, oop new_value); template - inline oop oop_xchg(DecoratorSet decorators, T* addr, oop new_value); + inline void keepalive_barrier(DecoratorSet decorators, T* addr, oop obj, Filter filter); - template - void write_ref_field_post(T* field, oop new_value); + template + inline oop load_reference_barrier(DecoratorSet decorators, oop obj, T* load_addr); - void write_ref_array(HeapWord* start, size_t count); + template + inline void arraycopy_barrier(T* src, T* dst, size_t count, bool dest_uninit); private: - template - void arraycopy_marking(T* dst, size_t count); + void keepalive_barrier_slow(oop obj, Filter filter); - template + template + oop load_reference_barrier_slow(oop obj, T* load_addr); + + template bool is_above_tams(const ShenandoahMarkingContext* ctx, T* dst) const; - template - inline void arraycopy_evacuation(T* src, size_t count); - template - inline void arraycopy_update(T* src, size_t count); + template + void arraycopy_marking(T* dst, size_t count); + + template + void arraycopy_evacuation(T* src, size_t count); + + template + void arraycopy_update(T* src, size_t count); + + void clone_evacuation(oop src); - template - inline void clone_work(oop src); + void clone_update(oop src); + + template + inline void card_barrier(T* field, oop new_value); + + inline void card_barrier_array(HeapWord* start, size_t count); + + void card_barrier_array_slow(HeapWord* start, size_t count); + + bool need_bulk_update(HeapWord* dst) const; - inline bool need_bulk_update(HeapWord* dst) const; public: // Callbacks for runtime accesses. template @@ -144,11 +164,8 @@ class ShenandoahBarrierSet: public BarrierSet { typedef BarrierSet::AccessBarrier Raw; private: - template - static oop oop_load_common(DecoratorSet resolved_decorators, T* addr); - - template - static void oop_store_common(T* addr, oop value); + static DecoratorSet resolve_unknown(oop base, ptrdiff_t offset); + static DecoratorSet resolve_unknown_to_strong(oop base, ptrdiff_t offset); public: // Heap oop accesses. These accessors get resolved when diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index b2f5fbad5cf0..a27516f97378 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -34,7 +34,6 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" -#include "gc/shenandoah/shenandoahForwarding.inline.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" @@ -43,86 +42,14 @@ #include "memory/iterator.inline.hpp" #include "oops/oop.inline.hpp" -template -inline oop ShenandoahBarrierSet::load_reference_barrier_mutator(oop obj, T* load_addr) { - assert(ShenandoahLoadRefBarrier, "Should be enabled"); - - constexpr bool on_weak = HasDecorator::value; - constexpr bool on_phantom = HasDecorator::value; - - // Handle nulls. Strong loads filtered nulls with cset checks. - // Weak/phantom loads need to check for nulls here. - if (on_weak || on_phantom) { - if (obj == nullptr) { - return nullptr; - } - } else { - assert(obj != nullptr, "Should have been filtered before"); - } - - // Prevent resurrection of unreachable phantom (i.e. weak-native) references. - if (on_phantom && - _heap->is_concurrent_weak_root_in_progress() && - _heap->is_in_active_generation(obj) && - !_heap->marking_context()->is_marked(obj)) { - return nullptr; - } - - // Prevent resurrection of unreachable weak references. - if (on_weak && - _heap->is_concurrent_weak_root_in_progress() && - _heap->is_in_active_generation(obj) && - !_heap->marking_context()->is_marked_strong(obj)) { - return nullptr; - } - - // Weak/phantom loads need additional cset check. - if (on_phantom || on_weak) { - if (!_heap->has_forwarded_objects() || !_heap->in_collection_set(obj)) { - return obj; - } - } else { - shenandoah_assert_in_cset(load_addr, obj); - } - - oop fwd = ShenandoahForwarding::get_forwardee_mutator(obj); - if (obj == fwd) { - assert(_heap->is_evacuation_in_progress(), "evac should be in progress"); - Thread* const t = Thread::current(); - fwd = _heap->evacuate_object(obj, t); - } - - if (load_addr != nullptr && fwd != obj) { - // Since we are here and we know the load address, update the reference. - ShenandoahHeap::atomic_update_oop(fwd, load_addr, obj); - } - - return fwd; -} - -inline oop ShenandoahBarrierSet::load_reference_barrier(oop obj) { - if (!ShenandoahLoadRefBarrier) { - return obj; - } - if (_heap->has_forwarded_objects() && _heap->in_collection_set(obj)) { - // Subsumes null-check - assert(obj != nullptr, "cset check must have subsumed null-check"); - oop fwd = ShenandoahForwarding::get_forwardee(obj); - if (obj == fwd && _heap->is_evacuation_in_progress()) { - Thread* t = Thread::current(); - return _heap->evacuate_object(obj, t); - } - return fwd; - } - return obj; -} - -template +template inline oop ShenandoahBarrierSet::load_reference_barrier(DecoratorSet decorators, oop obj, T* load_addr) { if (obj == nullptr) { return nullptr; } + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); + // Prevent resurrection of unreachable phantom (i.e. weak-native) references. if ((decorators & ON_PHANTOM_OOP_REF) != 0 && _heap->is_concurrent_weak_root_in_progress() && @@ -146,70 +73,54 @@ inline oop ShenandoahBarrierSet::load_reference_barrier(DecoratorSet decorators, return obj; } - oop fwd = load_reference_barrier(obj); - if (load_addr != nullptr && fwd != obj) { - // Since we are here and we know the load address, update the reference. - ShenandoahHeap::atomic_update_oop(fwd, load_addr, obj); + // No need for the barrier if object is not forwarded. + if (!_heap->has_forwarded_objects() || !_heap->in_collection_set(obj)) { + return obj; } - return fwd; + return load_reference_barrier_slow(obj, load_addr); } -inline void ShenandoahBarrierSet::enqueue(oop obj, bool filter) { - assert(obj != nullptr, "checked by caller"); - shenandoah_assert_correct(nullptr, obj); - assert(_satb_mark_queue_set.is_active(), "only get here when SATB active"); - - // Filter marked objects before hitting the SATB queues. The same predicate would - // be used by SATBMQ::filter to eliminate already marked objects downstream, but - // filtering here helps to avoid wasteful SATB queueing work to begin with. - if (filter && !_heap->requires_marking(obj)) return; +template +inline void ShenandoahBarrierSet::keepalive_barrier(DecoratorSet decorators, T* addr, oop obj, Filter filter) { + // Uninitialized and no-keepalive loads/stores do not need barrier. + if (((decorators & IS_DEST_UNINITIALIZED) != 0) || + ((decorators & AS_NO_KEEPALIVE) != 0)) { + return; + } - SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(Thread::current()); - _satb_mark_queue_set.enqueue_known_active(queue, obj); -} + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); -template -inline void ShenandoahBarrierSet::satb_barrier(T *field) { - // Uninitialized and no-keepalive stores do not need barrier. - if (HasDecorator::value || - HasDecorator::value) { + // No need for barriers on weaks, if requested. Normally filtered for stores, accepted for loads. + if (((filter & FILTER_WEAK) != 0) && + (((decorators & ON_WEAK_OOP_REF) != 0) || + ((decorators & ON_PHANTOM_OOP_REF) != 0))) { return; } - // Stores to weak/phantom require no barrier. The original references would - // have been enqueued in the SATB buffer by the load barrier if they were needed. - if (HasDecorator::value || - HasDecorator::value) { + // No need for the barrier if marking is not in progress. + if (!_heap->is_concurrent_mark_in_progress()) { return; } - if (ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) { - T heap_oop = RawAccess<>::oop_load(field); - if (!CompressedOops::is_null(heap_oop)) { - enqueue(CompressedOops::decode_not_null(heap_oop)); - } + if (addr != nullptr) { + assert(obj == nullptr, "Ambiguity: use addr or obj?"); + obj = RawAccess<>::oop_load(addr); } -} -inline void ShenandoahBarrierSet::satb_enqueue(oop value) { - if (value != nullptr && ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) { - enqueue(value); + // Null objects require no barriers. + if (obj == nullptr) { + return; } -} -inline void ShenandoahBarrierSet::keep_alive_if_weak(DecoratorSet decorators, oop value) { - assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); - const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; - const bool peek = (decorators & AS_NO_KEEPALIVE) != 0; - if (!peek && !on_strong_oop_ref) { - satb_enqueue(value); - } + keepalive_barrier_slow(obj, filter); } -template -inline void ShenandoahBarrierSet::write_ref_field_post(T* field, oop new_value) { - assert(ShenandoahCardBarrier, "Should have been checked by caller"); +template +inline void ShenandoahBarrierSet::card_barrier(T* field, oop new_value) { + if (!ShenandoahCardBarrier) { + return; + } if (new_value == nullptr) { // Null reference stores do not require card mark. @@ -233,241 +144,232 @@ inline void ShenandoahBarrierSet::write_ref_field_post(T* field, oop new_value) *byte = CardTable::dirty_card_val(); } +inline void ShenandoahBarrierSet::card_barrier_array(HeapWord* start, size_t count) { + if (!ShenandoahCardBarrier) { + return; + } + card_barrier_array_slow(start, count); +} + +template +inline oop ShenandoahBarrierSet::oop_load_post(DecoratorSet decorators, oop value, T* addr) { + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); + + shenandoah_assert_not_in_cset_loc_except(addr, !is_heap_access(decorators) || _heap->cancelled_gc()); + + // Perform LRB to handle evacuation and possibly weak loads. + value = load_reference_barrier(decorators, value, addr); + + // If weak load survived the LRB, we need to keep-alive the value. + if (!is_strong_access(decorators)) { + keepalive_barrier(decorators, (T*)nullptr, value, FILTER_MARKED); + } + + return value; +} + +template +inline void ShenandoahBarrierSet::oop_store_pre(DecoratorSet decorators, T* addr, oop new_value) { + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); + + shenandoah_assert_not_in_cset_loc_except(addr, !is_heap_access(decorators) || _heap->cancelled_gc()); + shenandoah_assert_not_in_cset_except(nullptr, new_value, new_value == nullptr || _heap->cancelled_gc()); + shenandoah_assert_not_forwarded_except(nullptr, new_value, new_value == nullptr || _heap->cancelled_gc()); + + shenandoah_assert_marked_if(nullptr, new_value, + !CompressedOops::is_null(new_value) && + _heap->is_evacuation_in_progress() && + !(_heap->active_generation()->is_young() && _heap->heap_region_containing(new_value)->is_old())); + + // Handle the previous value through SATB, as we are about to perform the store. + keepalive_barrier(decorators, addr, nullptr, FILTER_WEAK_AND_MARKED); +} + template -inline oop ShenandoahBarrierSet::oop_cmpxchg(DecoratorSet decorators, T* addr, oop compare_value, oop new_value) { - shenandoah_assert_not_in_cset_except(nullptr, compare_value, (compare_value == nullptr || ShenandoahHeap::heap()->cancelled_gc())); - shenandoah_assert_not_in_cset_except(nullptr, new_value, (new_value == nullptr || ShenandoahHeap::heap()->cancelled_gc())); +inline void ShenandoahBarrierSet::oop_store_post(DecoratorSet decorators, T* addr, oop new_value) { + // Handle card table updates if needed. + if (is_heap_access(decorators)) { + card_barrier(addr, new_value); + } +} + +template +inline void ShenandoahBarrierSet::oop_cmpxchg_pre(DecoratorSet decorators, T* addr, oop compare_value, oop new_value) { + assert((decorators & AS_NO_KEEPALIVE) == 0, "CAS only with keep-alive"); + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "CAS should have resolved ref strength"); + assert((decorators & ON_STRONG_OOP_REF) != 0, "CAS only for strong refs"); + + shenandoah_assert_not_in_cset_loc_except(addr, !is_heap_access(decorators) || _heap->cancelled_gc()); + shenandoah_assert_not_in_cset_except(nullptr, compare_value, compare_value == nullptr || _heap->cancelled_gc()); + shenandoah_assert_not_in_cset_except(nullptr, new_value, new_value == nullptr || _heap->cancelled_gc()); + shenandoah_assert_not_forwarded_except(addr, compare_value, compare_value == nullptr || _heap->cancelled_gc()); + shenandoah_assert_not_forwarded_except(addr, new_value, new_value == nullptr || _heap->cancelled_gc()); // Handle the previous value through SATB, as we are about to perform the store. oop prev = RawAccess<>::oop_load(addr); - satb_enqueue(prev); + keepalive_barrier(decorators, (T*)nullptr, prev, FILTER_MARKED); // Perform LRB on location to fix it up for this and all following accesses. // This guarantees there are no false negatives due to concurrent evacuation, // and the value loaded later by CAS is sanitized by some LRB, or is null. load_reference_barrier(decorators, prev, addr); - - return RawAccess<>::oop_atomic_cmpxchg(addr, compare_value, new_value); } template -inline oop ShenandoahBarrierSet::oop_xchg(DecoratorSet decorators, T* addr, oop new_value) { - shenandoah_assert_not_in_cset_except(nullptr, new_value, (new_value == nullptr || ShenandoahHeap::heap()->cancelled_gc())); +inline void ShenandoahBarrierSet::oop_xchg_pre(DecoratorSet decorators, T* addr, oop new_value) { + assert((decorators & AS_NO_KEEPALIVE) == 0, "XCHG only with keep-alive"); + assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "XCHG should have resolved ref strength"); + assert((decorators & ON_STRONG_OOP_REF) != 0, "XCHG only for strong refs"); + + shenandoah_assert_not_in_cset_loc_except(addr, !is_heap_access(decorators) || _heap->cancelled_gc()); + shenandoah_assert_not_in_cset_except(nullptr, new_value, new_value == nullptr || _heap->cancelled_gc()); + shenandoah_assert_not_forwarded_except(addr, new_value, new_value == nullptr || _heap->cancelled_gc()); // Handle the previous value through SATB, as we are about to perform the store. oop prev = RawAccess<>::oop_load(addr); - satb_enqueue(prev); + keepalive_barrier(decorators, (T*)nullptr, prev, FILTER_MARKED); // Perform LRB on location to fix it up for this and all following accesses. // This is purely opportunistic: we would not have any false negatives here. // This guarantees the value loaded later by XCHG is sanitized by some LRB, or is null. load_reference_barrier(decorators, prev, addr); +} - return RawAccess<>::oop_atomic_xchg(addr, new_value); +template +inline DecoratorSet ShenandoahBarrierSet::AccessBarrier::resolve_unknown(oop base, ptrdiff_t offset) { + return AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset); } template -template -inline oop ShenandoahBarrierSet::AccessBarrier::oop_load_common(DecoratorSet resolved_decorators, T* addr) { - // This raw access inherits decorators that are needed for proper memory ordering. - oop value = Raw::template oop_load(addr); - ShenandoahBarrierSet* bs = barrier_set(); - value = bs->load_reference_barrier(resolved_decorators, value, addr); - bs->keep_alive_if_weak(resolved_decorators, value); - return value; +inline DecoratorSet ShenandoahBarrierSet::AccessBarrier::resolve_unknown_to_strong(oop base, ptrdiff_t offset) { + // Unsafe operations come to this barrier set with ON_UNKNOWN_OOP_REF set. + // These are normally strong refs, but one can use Unsafe on Reference.referent. + // We cannot deal with that case. If application does Unsafe operations on + // Reference.referent field, this likely breaks weak reference semantics already. + // We upgrade the access to strong in (sometimes futile) attempt to maintain heap + // integrity, and assert in debug builds for better diagnostics. + assert((decorators & (ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF)) != 0, "Only strong or unknown expected here"); + DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset); + assert((resolved_decorators & ON_STRONG_OOP_REF) != 0, "Application error: Unsupported operation on weak location"); + return (resolved_decorators & ~ON_DECORATOR_MASK) | ON_STRONG_OOP_REF; } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_load_not_in_heap(T* addr) { - assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "must be absent"); - return oop_load_common(decorators, addr); + oop value = Raw::oop_load_not_in_heap(addr); + return barrier_set()->oop_load_post(decorators, value, addr); } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_load_in_heap(T* addr) { - assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "must be absent"); - return oop_load_common(decorators, addr); + oop value = Raw::oop_load_in_heap(addr); + return barrier_set()->oop_load_post(decorators, value, addr); } template inline oop ShenandoahBarrierSet::AccessBarrier::oop_load_in_heap_at(oop base, ptrdiff_t offset) { - DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset); - return oop_load_common(resolved_decorators, AccessInternal::oop_field_addr(base, offset)); -} - -template -template -inline void ShenandoahBarrierSet::AccessBarrier::oop_store_common(T* addr, oop value) { - shenandoah_assert_marked_if(nullptr, value, - !CompressedOops::is_null(value) && ShenandoahHeap::heap()->is_evacuation_in_progress() - && !(ShenandoahHeap::heap()->active_generation()->is_young() - && ShenandoahHeap::heap()->heap_region_containing(value)->is_old())); - shenandoah_assert_not_in_cset_if(addr, value, value != nullptr && !ShenandoahHeap::heap()->cancelled_gc()); - ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set(); - bs->satb_barrier(addr); - Raw::oop_store(addr, value); + DecoratorSet resolved_decorators = resolve_unknown(base, offset); + auto addr = AccessInternal::oop_field_addr(base, offset); + oop value = Raw::oop_load_in_heap(addr); + return barrier_set()->oop_load_post(resolved_decorators, value, addr); } template template inline void ShenandoahBarrierSet::AccessBarrier::oop_store_not_in_heap(T* addr, oop value) { - assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); - oop_store_common(addr, value); + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_store_pre(decorators, addr, value); + Raw::oop_store_not_in_heap(addr, value); + bs->oop_store_post(decorators, addr, value); } template template inline void ShenandoahBarrierSet::AccessBarrier::oop_store_in_heap(T* addr, oop value) { - shenandoah_assert_not_in_cset_loc_except(addr, ShenandoahHeap::heap()->cancelled_gc()); - shenandoah_assert_not_forwarded_except (addr, value, value == nullptr || ShenandoahHeap::heap()->cancelled_gc() || !ShenandoahHeap::heap()->is_concurrent_mark_in_progress()); - - oop_store_common(addr, value); - if (ShenandoahCardBarrier) { - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - bs->write_ref_field_post(addr, value); - } + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_store_pre(decorators, addr, value); + Raw::oop_store_in_heap(addr, value); + bs->oop_store_post(decorators, addr, value); } template inline void ShenandoahBarrierSet::AccessBarrier::oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { - oop_store_in_heap(AccessInternal::oop_field_addr(base, offset), value); + auto addr = AccessInternal::oop_field_addr(base, offset); + + // In contrast to CASes, we resolve unknown to weak/phantom access, because some code + // legitimately enters here, e.g. for clearing Reference.referent. + DecoratorSet resolved_decorators = resolve_unknown(base, offset); + + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_store_pre(resolved_decorators, addr, value); + Raw::oop_store_in_heap(addr, value); + bs->oop_store_post(resolved_decorators, addr, value); } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_cmpxchg_not_in_heap(T* addr, oop compare_value, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "CAS only with keep-alive"); - assert((decorators & ON_STRONG_OOP_REF) != 0, "CAS only for strong refs"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - return bs->oop_cmpxchg(decorators, addr, compare_value, new_value); + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_cmpxchg_pre(decorators, addr, compare_value, new_value); + oop result = Raw::oop_atomic_cmpxchg_not_in_heap(addr, compare_value, new_value); + bs->oop_store_post(decorators, addr, new_value); + return result; } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "CAS only with keep-alive"); - assert((decorators & ON_STRONG_OOP_REF) != 0, "CAS only for strong refs"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - oop result = bs->oop_cmpxchg(decorators, addr, compare_value, new_value); - if (ShenandoahCardBarrier) { - bs->write_ref_field_post(addr, new_value); - } + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_cmpxchg_pre(decorators, addr, compare_value, new_value); + oop result = Raw::oop_atomic_cmpxchg_in_heap(addr, compare_value, new_value); + bs->oop_store_post(decorators, addr, new_value); return result; } template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "CAS only with keep-alive"); - assert((decorators & (ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF)) != 0, "CAS only for strong refs OR unknown refs (Unsafe)"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - - // Unsafe.compareAndExchange/Set come here with ON_UNKNOWN_OOP_REF set. - // These are normally strong refs, but one can use Unsafe on Reference.referent. - // We cannot deal with that case. If application does Unsafe operations on - // Reference.referent field, this likely breaks weak reference semantics already. - // We upgrade the access to strong in (sometimes futile) attempt to maintain heap - // integrity, and assert in debug builds for better diagnostics. - DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset); - assert((resolved_decorators & ON_STRONG_OOP_REF) != 0, "Application error: CAS on weak location"); - resolved_decorators = (resolved_decorators & ~ON_DECORATOR_MASK) | ON_STRONG_OOP_REF; - auto addr = AccessInternal::oop_field_addr(base, offset); - oop result = bs->oop_cmpxchg(resolved_decorators, addr, compare_value, new_value); - if (ShenandoahCardBarrier) { - bs->write_ref_field_post(addr, new_value); - } + DecoratorSet resolved_decorators = resolve_unknown_to_strong(base, offset); + + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_cmpxchg_pre(resolved_decorators, addr, compare_value, new_value); + oop result = Raw::oop_atomic_cmpxchg_in_heap(addr, compare_value, new_value); + bs->oop_store_post(resolved_decorators, addr, new_value); return result; } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_xchg_not_in_heap(T* addr, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "XCHG only with keep-alive"); - assert((decorators & ON_STRONG_OOP_REF) != 0, "XCHG only for strong refs"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - return bs->oop_xchg(decorators, addr, new_value); + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_xchg_pre(decorators, addr, new_value); + oop result = Raw::oop_atomic_xchg_not_in_heap(addr, new_value); + bs->oop_store_post(decorators, addr, new_value); + return result; } template template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_xchg_in_heap(T* addr, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "XCHG only with keep-alive"); - assert((decorators & ON_STRONG_OOP_REF) != 0, "XCHG only for strong refs"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - oop result = bs->oop_xchg(decorators, addr, new_value); - if (ShenandoahCardBarrier) { - bs->write_ref_field_post(addr, new_value); - } + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_xchg_pre(decorators, addr, new_value); + oop result = Raw::oop_atomic_xchg_in_heap(addr, new_value); + bs->oop_store_post(decorators, addr, new_value); return result; } template inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) { - assert((decorators & AS_NO_KEEPALIVE) == 0, "XCHG only with keep-alive"); - assert((decorators & (ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF)) != 0, "XCHG only for strong refs OR unknown refs (Unsafe)"); - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); - - // Unsafe.getAndSet comes here with ON_UNKNOWN_OOP_REF set. - // These are normally strong refs, but one can use Unsafe on Reference.referent. - // We cannot deal with that case. If application does Unsafe operations on - // Reference.referent field, this likely breaks weak reference semantics already. - // We upgrade the access to strong in (sometimes futile) attempt to maintain heap - // integrity, and assert in debug builds for better diagnostics. - DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset); - assert((resolved_decorators & ON_STRONG_OOP_REF) != 0, "Application error: XCHG on weak location"); - resolved_decorators = (resolved_decorators & ~ON_DECORATOR_MASK) | ON_STRONG_OOP_REF; - auto addr = AccessInternal::oop_field_addr(base, offset); - oop result = bs->oop_xchg(resolved_decorators, addr, new_value); - if (ShenandoahCardBarrier) { - bs->write_ref_field_post(addr, new_value); - } - return result; -} + DecoratorSet resolved_decorators = resolve_unknown_to_strong(base, offset); -// Clone barrier support -template -class ShenandoahUpdateEvacForCloneOopClosure : public BasicOopIterateClosure { -private: - ShenandoahHeap* const _heap; - const ShenandoahCollectionSet* const _cset; - Thread* const _thread; - - template - inline void do_oop_work(T* p) { - T o = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - if (_cset->is_in(obj)) { - oop fwd = ShenandoahForwarding::get_forwardee(obj); - if (EVAC && obj == fwd) { - fwd = _heap->evacuate_object(obj, _thread); - } - shenandoah_assert_forwarded_except(p, obj, _heap->cancelled_gc()); - ShenandoahHeap::atomic_update_oop(fwd, p, o); - obj = fwd; - } - } - } - -public: - ShenandoahUpdateEvacForCloneOopClosure() : - _heap(ShenandoahHeap::heap()), - _cset(_heap->collection_set()), - _thread(Thread::current()) {} - - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } -}; - -template -void ShenandoahBarrierSet::clone_work(oop obj) { - if (need_bulk_update(cast_from_oop(obj))) { - ShenandoahUpdateEvacForCloneOopClosure cl; - obj->oop_iterate(&cl); - } + ShenandoahBarrierSet* bs = barrier_set(); + bs->oop_xchg_pre(resolved_decorators, addr, new_value); + oop result = Raw::oop_atomic_xchg_in_heap(addr, new_value); + bs->oop_store_post(resolved_decorators, addr, new_value); + return result; } template @@ -476,12 +378,12 @@ void ShenandoahBarrierSet::AccessBarrier::clone_in_heap // Fix up src before doing the copy, if needed. const char gc_state = ShenandoahThreadLocalData::gc_state(Thread::current()); - if (gc_state != 0 && ShenandoahCloneBarrier) { - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); + if (gc_state != 0) { + ShenandoahBarrierSet* bs = barrier_set(); if ((gc_state & ShenandoahHeap::EVACUATION) != 0) { - bs->clone_work(src); + bs->clone_evacuation(src); } else if ((gc_state & ShenandoahHeap::UPDATE_REFS) != 0) { - bs->clone_work(src); + bs->clone_update(src); } } @@ -501,7 +403,7 @@ void ShenandoahBarrierSet::AccessBarrier::value_copy_in // If we do not have oops in the flat array, we can just do a raw copy. Raw::value_copy(src, dst); } else { - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); + ShenandoahBarrierSet* bs = barrier_set(); // addr() points at the payload start, the oop map offset are relative to // the object header, adjust address to account for this discrepancy. const address oop_map_adjusted_src_addr = src.addr() - md->payload_offset(); @@ -531,7 +433,7 @@ void ShenandoahBarrierSet::AccessBarrier::value_copy_in OopMapBlock* const end = map + md->nonstatic_oop_map_count(); while (map != end) { address dst_oop_address = oop_map_adjusted_dst_addr + map->offset(); - bs->write_ref_array((HeapWord*) dst_oop_address, map->count()); + bs->card_barrier_array((HeapWord*) dst_oop_address, map->count()); map++; } } @@ -579,16 +481,14 @@ OopCopyResult ShenandoahBarrierSet::AccessBarrier::oop_ T* dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); bool dest_uninit = HasDecorator::value; - ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set(); + ShenandoahBarrierSet* bs = barrier_set(); bs->arraycopy_barrier(src, dst, length, dest_uninit); OopCopyResult result = Raw::oop_arraycopy_in_heap(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); - if (ShenandoahCardBarrier) { - bs->write_ref_array((HeapWord*) dst, length); - } + bs->card_barrier_array((HeapWord*) dst, length); return result; } -template +template void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count, bool dest_uninit) { if (count == 0) { // No elements to copy, no need for barrier @@ -616,96 +516,4 @@ void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count, bool } } -template -void ShenandoahBarrierSet::arraycopy_marking(T* dst, size_t count) { - assert(_heap->is_concurrent_mark_in_progress(), "only during marking"); - if (!ShenandoahSATBBarrier) { - return; - } - - const ShenandoahMarkingContext* ctx = _heap->marking_context(); - // Everything allocated above TAMS is alive and doesn't need the barrier to keep it that way - if (is_above_tams(ctx, dst)) { - return; - } - - assert(!_heap->has_forwarded_objects() || _heap->is_concurrent_old_mark_in_progress(), "Forwarded object status is sane"); - Thread* thread = Thread::current(); - SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread); - T* end = dst + count; - for (T* elem_ptr = dst; elem_ptr < end; ++elem_ptr) { - T o = RawAccess<>::oop_load(elem_ptr); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - if (!ctx->is_marked_strong(obj)) { - _satb_mark_queue_set.enqueue_known_active(queue, obj); - } - } - } -} - -template -bool ShenandoahBarrierSet::is_above_tams(const ShenandoahMarkingContext* ctx, T* dst) const { - // TAMS for an old region is unreliable during a young-only mark, so overwritten pointers in old dst arrays must - // be enqueued to preserve old->young referents copied in and overwritten after init mark. See JDK-8373116. - return ctx->allocated_after_mark_start(reinterpret_cast(dst)) - && !(IS_GENERATIONAL - && _heap->heap_region_containing(dst)->is_old() - && _heap->is_concurrent_young_mark_in_progress()); -} - -inline bool ShenandoahBarrierSet::need_bulk_update(HeapWord* ary) const { - return ary < _heap->heap_region_containing(ary)->get_update_watermark(); -} - -template -void ShenandoahBarrierSet::arraycopy_evacuation(T* src, size_t count) { - assert(_heap->is_evacuation_in_progress(), "only during evacuation"); - if (!need_bulk_update(reinterpret_cast(src))) { - return; - } - - assert(_heap->has_forwarded_objects(), "Forwarded object status is sane"); - Thread* thread = Thread::current(); - const ShenandoahCollectionSet* const cset = _heap->collection_set(); - T* end = src + count; - for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) { - T o = RawAccess<>::oop_load(elem_ptr); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - if (cset->is_in(obj)) { - oop fwd = ShenandoahForwarding::get_forwardee(obj); - if (obj == fwd) { - fwd = _heap->evacuate_object(obj, thread); - } - shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); - ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); - } - } - } -} - -template -void ShenandoahBarrierSet::arraycopy_update(T* src, size_t count) { - assert(_heap->is_update_refs_in_progress(), "only during update-refs"); - if (!need_bulk_update(reinterpret_cast(src))) { - return; - } - - assert(_heap->has_forwarded_objects(), "Forwarded object status is sane"); - const ShenandoahCollectionSet* const cset = _heap->collection_set(); - T* end = src + count; - for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) { - T o = RawAccess<>::oop_load(elem_ptr); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - if (cset->is_in(obj)) { - oop fwd = ShenandoahForwarding::get_forwardee(obj); - shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); - ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); - } - } - } -} - #endif // SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetStackChunk.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetStackChunk.cpp index 224d9e1870a8..e881de8f4755 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetStackChunk.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetStackChunk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,10 +35,10 @@ void ShenandoahBarrierSetStackChunk::decode_gc_mode(stackChunkOop chunk, OopIter oop ShenandoahBarrierSetStackChunk::load_oop(stackChunkOop chunk, oop* addr) { oop result = BarrierSetStackChunk::load_oop(chunk, addr); - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(result); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, result, (oop*)nullptr); } oop ShenandoahBarrierSetStackChunk::load_oop(stackChunkOop chunk, narrowOop* addr) { oop result = BarrierSetStackChunk::load_oop(chunk, addr); - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(result); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, result, (narrowOop*)nullptr); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardStats.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCardStats.cpp index fc59af99817e..ba0b8c956ec9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardStats.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp index e9e52475fb92..3ce54f9e3bd6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -96,7 +96,7 @@ bool ShenandoahCardTable::is_in_young(const void* obj) const { return ShenandoahHeap::heap()->is_in_young(obj); } -CardValue* ShenandoahCardTable::read_byte_for(const void* p) { +CardTable::CardValue* ShenandoahCardTable::read_byte_for(const void* p) { CardValue* result = &_read_byte_map_base[uintptr_t(p) >> _card_shift]; assert(result >= _read_byte_map && result < _read_byte_map + _byte_map_size, "out of bounds accessor for card marking array"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp index eb40dfbd31d6..8b082b4127b0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp @@ -71,7 +71,7 @@ class ShenandoahMarkRefsSuperClosure : public ShenandoahSuperClosure { bool _weak; protected: - template + template void work(T *p); public: @@ -96,7 +96,7 @@ class ShenandoahMarkRefsClosure : public ShenandoahMarkRefsSuperClosure { private: template ALWAYSINLINE - void do_oop_work(T* p) { work(p); } + void do_oop_work(T* p) { work(p); } public: ShenandoahMarkRefsClosure(ShenandoahObjToScanQueue* q, ShenandoahReferenceProcessor* rp, ShenandoahObjToScanQueue* old_q) : @@ -109,6 +109,23 @@ class ShenandoahMarkRefsClosure : public ShenandoahMarkRefsSuperClosure { void do_oop(oop* p) override { do_oop_work(p); } }; +class ShenandoahRedirtyCardsMarkClosure : public ShenandoahMarkRefsSuperClosure { +private: + template + ALWAYSINLINE + void do_oop_work(T* p) { work(p); } + +public: + ShenandoahRedirtyCardsMarkClosure(ShenandoahObjToScanQueue* q, ShenandoahReferenceProcessor* rp, ShenandoahObjToScanQueue* old_q) + : ShenandoahMarkRefsSuperClosure(q, rp, old_q) {} + + ALWAYSINLINE + void do_oop(narrowOop* p) override { do_oop_work(p); } + + ALWAYSINLINE + void do_oop(oop* p) override { do_oop_work(p); } +}; + class ShenandoahForwardedIsAliveClosure : public BoolObjectClosure { private: ShenandoahMarkingContext* const _mark_context; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp index f57a9b209578..671d9586073a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp @@ -76,10 +76,10 @@ ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToSc _mark_context(ShenandoahHeap::heap()->marking_context()), _weak(false) {} -template +template ALWAYSINLINE void ShenandoahMarkRefsSuperClosure::work(T* p) { - ShenandoahMark::mark_through_ref(p, _queue, _old_queue, _mark_context, _weak); + ShenandoahMark::mark_through_ref(p, _queue, _old_queue, _mark_context, _weak); } ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() : @@ -118,12 +118,7 @@ template void ShenandoahKeepAliveClosure::do_oop_work(T* p) { assert(ShenandoahHeap::heap()->is_concurrent_mark_in_progress(), "Only for concurrent marking phase"); assert(ShenandoahHeap::heap()->is_concurrent_old_mark_in_progress() || !ShenandoahHeap::heap()->has_forwarded_objects(), "Not expected"); - - T o = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - _bs->enqueue(obj); - } + _bs->keepalive_barrier(ON_STRONG_OOP_REF, p, nullptr, ShenandoahBarrierSet::FILTER_MARKED); } @@ -229,7 +224,7 @@ inline void ShenandoahMarkUpdateRefsClosure::work(T* p) { _heap->non_conc_update_with_forwarded(p); // ...then do the usual thing - ShenandoahMarkRefsSuperClosure::work(p); + ShenandoahMarkRefsSuperClosure::work(p); } template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 2c82271f07f8..2cd1e1b1c39c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -97,7 +97,7 @@ void ShenandoahControlThread::run_service() { } } else if (is_gc_requested) { cause = requested_gc_cause; - heuristics->log_trigger("GC request (%s)", GCCause::to_string(cause)); + heuristics->log_trigger("GC Request (%s)", GCCause::to_string(cause)); heuristics->record_requested_gc(); if (ShenandoahCollectorPolicy::should_run_full_gc(cause)) { @@ -282,7 +282,8 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau // ShenandoahHeap* heap = ShenandoahHeap::heap(); if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) { - log_info(gc, phases)("Cancelled"); + // Need to report at "gc" level to report GC ID proper. + log_info(gc)("Cancelled before cycle started"); return; } heap->increment_total_collections(false); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp index 6f2f124f6b11..ca064ee5f2e9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp @@ -36,11 +36,6 @@ class ShenandoahForwarding { */ static inline oop get_forwardee(oop obj); - /* Gets forwardee from the given object. Only from mutator thread. - * For a self-forwarded object, returns the object itself. - */ - static inline oop get_forwardee_mutator(oop obj); - /* Returns the raw value from forwardee slot. For a self-forwarded * object, returns the object itself. */ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp index 6bb58920eb96..df0154871d7c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp @@ -53,21 +53,6 @@ inline oop ShenandoahForwarding::get_forwardee_raw_unchecked(oop obj) { return obj; } -inline oop ShenandoahForwarding::get_forwardee_mutator(oop obj) { - // Same as above, but mutator thread cannot ever see null forwardee. - shenandoah_assert_correct(nullptr, obj); - assert(Thread::current()->is_Java_thread(), "Must be a mutator thread"); - - markWord mark = obj->mark(); - if (mark.is_marked()) { - HeapWord* fwdptr = (HeapWord*) mark.clear_lock_bits().to_pointer(); - assert(fwdptr != nullptr, "Forwarding pointer is never null here"); - return cast_to_oop(fwdptr); - } - // Self-forwarded or not forwarded: return the object itself. - return obj; -} - inline oop ShenandoahForwarding::get_forwardee(oop obj) { shenandoah_assert_correct(nullptr, obj); return get_forwardee_raw_unchecked(obj); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 9db0f6627055..346ecd121fdb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -24,14 +24,13 @@ * */ -#include "gc/shared/tlab_globals.hpp" #include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahAllocator.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.inline.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/logStream.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 139406246693..40463a525ba5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,12 @@ */ #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" @@ -258,17 +260,12 @@ void ShenandoahGeneration::prepare_regions_and_collection_set(bool concurrent) { { ShenandoahGCPhase phase(concurrent ? ShenandoahPhaseTimings::final_update_region_states : ShenandoahPhaseTimings::degen_gc_final_update_region_states); - ShenandoahFinalMarkUpdateRegionStateClosure cl(complete_marking_context()); - parallel_heap_region_iterate(&cl); - - if (is_young()) { - // We always need to update the watermark for old regions. If there - // are mixed collections pending, we also need to synchronize the - // pinned status for old regions. Since we are already visiting every - // old region here, go ahead and sync the pin status too. - ShenandoahFinalMarkUpdateRegionStateClosure old_cl(nullptr); - heap->old_generation()->parallel_heap_region_iterate(&old_cl); - } + // Update region state for every active region, but only update the liveness data for + // the generation we marked. We always need to update the watermark for old regions. + // If there are mixed collections pending, we also need to synchronize the pinned status + // for old regions. + ShenandoahFinalMarkUpdateRegionStateClosure cl(complete_marking_context(), this); + heap->global_generation()->parallel_heap_region_iterate(&cl); } // Tally the census counts and compute the adaptive tenuring threshold @@ -325,12 +322,16 @@ bool ShenandoahGeneration::is_bitmap_clear() { ShenandoahMarkingContext* context = heap->marking_context(); const size_t num_regions = heap->num_regions(); for (size_t idx = 0; idx < num_regions; idx++) { + const ShenandoahAffiliation affiliation = heap->region_affiliation(idx); + if (!contains(affiliation) || affiliation == FREE) { + // Skip regions outside this generation or those that are unaffiliated + continue; + } + ShenandoahHeapRegion* r = heap->get_region(idx); - if (contains(r) && r->is_affiliated()) { - if (heap->is_bitmap_slice_committed(r) && (context->top_at_mark_start(r) > r->bottom()) && - !context->is_bitmap_range_within_region_clear(r->bottom(), r->end())) { - return false; - } + if (heap->is_bitmap_slice_committed(r) && (context->top_at_mark_start(r) > r->bottom()) && + !context->is_bitmap_range_within_region_clear(r->bottom(), r->end())) { + return false; } } return true; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 9f8944127c00..b58f91e7a7e9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -140,7 +140,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { // Cancel marking (used by Full collect and when cancelling cycle). virtual void cancel_marking(); - virtual bool contains(ShenandoahAffiliation affiliation) const = 0; + virtual bool contains(ShenandoahAffiliation affiliation) const override = 0; // Return true if this region is affiliated with this generation. virtual bool contains(ShenandoahHeapRegion* region) const override = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index c59f4992a7e2..6c3ee675cd0c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -184,7 +184,7 @@ ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread: ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread::prepare_for_explicit_gc(ShenandoahGCRequest &request) const { ShenandoahHeuristics* global_heuristics = _heap->global_generation()->heuristics(); request.generation = _heap->global_generation(); - global_heuristics->log_trigger("GC request (%s)", GCCause::to_string(request.cause)); + global_heuristics->log_trigger("GC Request (%s)", GCCause::to_string(request.cause)); global_heuristics->record_requested_gc(); if (ShenandoahCollectorPolicy::should_run_full_gc(request.cause)) { @@ -218,10 +218,12 @@ void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const LogStream ls(lt); AgeTable young_region_ages(false); for (uint i = 0; i < _heap->num_regions(); ++i) { - const ShenandoahHeapRegion* r = _heap->get_region(i); - if (r->is_young()) { - young_region_ages.add(r->age(), r->get_live_data_words()); + if (!_heap->is_region_young(i)) { + continue; } + + const ShenandoahHeapRegion* r = _heap->get_region(i); + young_region_ages.add(r->age(), r->get_live_data_words()); } ls.print("Young regions: "); @@ -403,7 +405,8 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const She // acknowledge the cancellation request, the subsequent young cycle will observe // the request and essentially cancel itself. if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) { - log_info(gc, thread)("Preparation for old generation cycle was cancelled"); + // Need to report at "gc" level to report GC ID proper. + log_info(gc)("Preparation for old generation cycle was cancelled"); return; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 323453756838..cfd33994e5fd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -25,12 +25,14 @@ #include "gc/shared/fullGCForwarding.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalFullGC.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahScanRemembered.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" @@ -106,10 +108,11 @@ void ShenandoahGenerationalFullGC::log_live_in_old(ShenandoahHeap* heap) { if (lt.is_enabled()) { size_t live_bytes_in_old = 0; for (size_t i = 0; i < heap->num_regions(); i++) { - ShenandoahHeapRegion* r = heap->get_region(i); - if (r->is_old()) { - live_bytes_in_old += r->get_live_data_bytes(); + if (!heap->is_region_old(i)) { + continue; } + + live_bytes_in_old += heap->get_region(i)->get_live_data_bytes(); } log_debug(gc)("Live bytes in old after STW mark: " PROPERFMT, PROPERFMTARGS(live_bytes_in_old)); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index ef4ee13a7d41..63a8666f816f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,10 +211,7 @@ oop ShenandoahGenerationalHeap::evacuate_object(oop p, Thread* thread) { return ShenandoahForwarding::get_forwardee(p); } - if (mark.has_displaced_mark_helper()) { - // We don't want to deal with MT here just to ensure we read the right mark word. - // Skip the potential promotion attempt for this one. - } else if (age_census()->is_tenurable(from_region->age() + mark.age())) { + if (age_census()->is_tenurable(from_region->age() + mark.age())) { // If the object is tenurable, try to promote it oop result = try_evacuate_object(p, thread, from_region->age()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index de660badd9ac..0039bda9605b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -410,6 +410,7 @@ jint ShenandoahHeap::initialize() { _regions = NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, _num_regions, mtGC); _affiliations = NEW_C_HEAP_ARRAY(uint8_t, _num_regions, mtGC); + _biased_affiliations = _affiliations - (p2u(base()) >> ShenandoahHeapRegion::region_size_bytes_shift()); { ShenandoahHeapLocker locker(lock()); @@ -568,6 +569,7 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : _num_regions(0), _regions(nullptr), _affiliations(nullptr), + _biased_affiliations(nullptr), _gc_state_changed(false), _gc_no_progress_count(0), _cancel_requested_time(0), @@ -1747,19 +1749,17 @@ class ObjectIterateScanRootClosure : public BasicOopIterateClosure { private: MarkBitMap* _bitmap; ShenandoahScanObjectStack* _oop_stack; - ShenandoahHeap* const _heap; - ShenandoahMarkingContext* const _marking_context; template void do_oop_work(T* p) { T o = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(o)) { oop obj = CompressedOops::decode_not_null(o); - if (_heap->is_concurrent_weak_root_in_progress() && !_marking_context->is_marked(obj)) { - // There may be dead oops in weak roots in concurrent root phase, do not touch them. + obj = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, obj, (T*)nullptr); + if (obj == nullptr) { + // Dead oop, cannot touch it. return; } - obj = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(obj); assert(oopDesc::is_oop(obj), "must be a valid oop"); if (!_bitmap->is_marked(obj)) { @@ -1770,8 +1770,7 @@ class ObjectIterateScanRootClosure : public BasicOopIterateClosure { } public: ObjectIterateScanRootClosure(MarkBitMap* bitmap, ShenandoahScanObjectStack* oop_stack) : - _bitmap(bitmap), _oop_stack(oop_stack), _heap(ShenandoahHeap::heap()), - _marking_context(_heap->marking_context()) {} + _bitmap(bitmap), _oop_stack(oop_stack) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } }; @@ -1859,20 +1858,17 @@ class ShenandoahObjectIterateParScanClosure : public BasicOopIterateClosure { private: MarkBitMap* _bitmap; ShenandoahObjToScanQueue* _queue; - ShenandoahHeap* const _heap; - ShenandoahMarkingContext* const _marking_context; template void do_oop_work(T* p) { T o = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(o)) { oop obj = CompressedOops::decode_not_null(o); - if (_heap->is_concurrent_weak_root_in_progress() && !_marking_context->is_marked(obj)) { - // There may be dead oops in weak roots in concurrent root phase, do not touch them. + obj = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, obj, (T*)nullptr); + if (obj == nullptr) { + // Dead oop, cannot touch it. return; } - obj = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(obj); - assert(oopDesc::is_oop(obj), "Must be a valid oop"); if (_bitmap->par_mark(obj)) { _queue->push(ShenandoahMarkTask(obj)); @@ -1881,8 +1877,7 @@ class ShenandoahObjectIterateParScanClosure : public BasicOopIterateClosure { } public: ShenandoahObjectIterateParScanClosure(MarkBitMap* bitmap, ShenandoahObjToScanQueue* q) : - _bitmap(bitmap), _queue(q), _heap(ShenandoahHeap::heap()), - _marking_context(_heap->marking_context()) {} + _bitmap(bitmap), _queue(q) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } }; @@ -1997,9 +1992,7 @@ ParallelObjectIteratorImpl* ShenandoahHeap::parallel_object_iterator(uint worker // Keep alive an object that was loaded with AS_NO_KEEPALIVE. void ShenandoahHeap::keep_alive(oop obj) { - if (is_concurrent_mark_in_progress() && (obj != nullptr)) { - ShenandoahBarrierSet::barrier_set()->enqueue(obj); - } + ShenandoahBarrierSet::barrier_set()->keepalive_barrier(ON_STRONG_OOP_REF, (oop*)nullptr, obj, ShenandoahBarrierSet::FILTER_MARKED); } void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const { @@ -2505,11 +2498,14 @@ void ShenandoahHeap::assert_pinned_region_status() const { void ShenandoahHeap::assert_pinned_region_status(ShenandoahGeneration* generation) const { for (size_t i = 0; i < num_regions(); i++) { - ShenandoahHeapRegion* r = get_region(i); - if (generation->contains(r)) { - assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0), - "Region %zu pinning status is inconsistent", i); + if (!generation->contains(region_affiliation(i))) { + // Skip regions outside this generation + continue; } + + ShenandoahHeapRegion* r = get_region(i); + assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0), + "Region %zu pinning status is inconsistent", i); } } #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index f26bb0d80cc3..bf84d60382e9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -287,6 +287,7 @@ class ShenandoahHeap : public CollectedHeap { size_t _num_regions; ShenandoahHeapRegion** _regions; uint8_t* _affiliations; // Holds array of enum ShenandoahAffiliation, including FREE status in non-generational mode + uint8_t* _biased_affiliations; public: @@ -634,6 +635,15 @@ class ShenandoahHeap : public CollectedHeap { inline bool is_in_young(const void* p) const; inline bool is_in_old(const void* p) const; + // Returns true if `maybe_old` is in old and `maybe_young` is in young + inline bool is_old_to_young(const void* maybe_old, oop maybe_young) const; + + // Returns false if `p` is not in the heap or does not have the given affiliation. + inline bool has_affiliation(const void* p, ShenandoahAffiliation affiliation) const; + + // Does not check that `obj` is in the heap (debug builds assert that `obj` is in the heap). + inline bool has_affiliation(oop obj, ShenandoahAffiliation affiliation) const; + // Returns true iff the young generation is being collected and the given pointer // is in the old generation. This is used to prevent the young collection from treating // such an object as unreachable. @@ -644,6 +654,10 @@ class ShenandoahHeap : public CollectedHeap { inline ShenandoahAffiliation region_affiliation(size_t index) const; + inline bool is_region_young(size_t index) const; + inline bool is_region_old(size_t index) const; + inline bool is_region_free(size_t index) const; + bool requires_barriers(stackChunkOop obj) const override; MemRegion reserved_region() const { return _reserved; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index ff0271db8fda..55e7f5845aab 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -37,6 +37,7 @@ #include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "gc/shared/tlab_globals.hpp" #include "gc/shenandoah/mode/shenandoahMode.hpp" +#include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" @@ -301,32 +302,18 @@ inline HeapWord* ShenandoahHeap::allocate_from_gclab(Thread* thread, size_t size void ShenandoahHeap::increase_object_age(oop obj, uint additional_age) { // This operates on new copy of an object. This means that the object's mark-word - // is thread-local and therefore safe to access. However, when the mark is - // displaced (i.e. stack-locked or monitor-locked), then it must be considered - // a shared memory location. It can be accessed by other threads. - // In particular, a competing evacuating thread can succeed to install its copy - // as the forwardee and continue to unlock the object, at which point 'our' - // write to the foreign stack-location would potentially over-write random - // information on that stack. Writing to a monitor is less problematic, - // but still not safe: while the ObjectMonitor would not randomly disappear, - // the other thread would also write to the same displaced header location, - // possibly leading to increase the age twice. - // For all these reasons, we take the conservative approach and not attempt - // to increase the age when the header is displaced. + // is thread-local and therefore safe to access. markWord w = obj->mark(); // It is possible that we have copied the object after another thread has // already successfully completed evacuation. While harmless (we would never // publish our copy), don't even attempt to modify the age when that // happens. - if (!w.has_displaced_mark_helper() && !w.is_marked()) { + if (!w.is_marked()) { w = w.set_age(MIN2(markWord::max_age, w.age() + additional_age)); obj->set_mark(w); } } -// Return the object's age, or a sentinel value when the age can't -// necessarily be determined because of concurrent locking by the -// mutator uint ShenandoahHeap::get_object_age(oop obj) { markWord w = obj->mark(); assert(!w.is_marked(), "must not be forwarded"); @@ -375,11 +362,36 @@ inline bool ShenandoahHeap::is_in_active_generation(oop obj) const { } inline bool ShenandoahHeap::is_in_young(const void* p) const { - return is_in_reserved(p) && (region_affiliation(heap_region_index_containing(p)) == ShenandoahAffiliation::YOUNG_GENERATION); + return has_affiliation(p, YOUNG_GENERATION); } inline bool ShenandoahHeap::is_in_old(const void* p) const { - return is_in_reserved(p) && (region_affiliation(heap_region_index_containing(p)) == ShenandoahAffiliation::OLD_GENERATION); + return has_affiliation(p, OLD_GENERATION); +} + +inline bool ShenandoahHeap::is_old_to_young(const void* maybe_old, oop maybe_young) const { + if (maybe_young == nullptr) { + return false; + } + if (ShenandoahHeapRegion::is_in_same_region(maybe_old, maybe_young)) { + return false; + } + return has_affiliation(maybe_old, OLD_GENERATION) && has_affiliation(maybe_young, YOUNG_GENERATION); +} + +inline bool ShenandoahHeap::has_affiliation(const void* p, ShenandoahAffiliation affiliation) const { + if (!is_in_reserved(p)) { + return false; + } + + const size_t index = p2u(p) >> ShenandoahHeapRegion::region_size_bytes_shift(); + return AtomicAccess::load(_biased_affiliations + index) == affiliation; +} + +inline bool ShenandoahHeap::has_affiliation(oop obj, ShenandoahAffiliation affiliation) const { + assert(is_in_reserved(obj), "Expected decoded oop (" PTR_FORMAT ") to be in the heap", p2i(obj)); + const size_t index = p2u(obj) >> ShenandoahHeapRegion::region_size_bytes_shift(); + return AtomicAccess::load(_biased_affiliations + index) == affiliation; } inline bool ShenandoahHeap::is_in_old_during_young_collection(oop obj) const { @@ -422,6 +434,18 @@ inline ShenandoahAffiliation ShenandoahHeap::region_affiliation(size_t index) co return (ShenandoahAffiliation) AtomicAccess::load(_affiliations + index); } +inline bool ShenandoahHeap::is_region_young(size_t index) const { + return region_affiliation(index) == YOUNG_GENERATION; +} + +inline bool ShenandoahHeap::is_region_old(size_t index) const { + return region_affiliation(index) == OLD_GENERATION; +} + +inline bool ShenandoahHeap::is_region_free(size_t index) const { + return region_affiliation(index) == FREE; +} + inline bool ShenandoahHeap::requires_marking(const void* entry) const { oop obj = cast_to_oop(entry); return !_marking_context->is_marked_strong(obj); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp index 98fc9040df96..8074aac151b3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp @@ -370,6 +370,10 @@ class ShenandoahHeapRegion { return _index; } + static bool is_in_same_region(const void* p, oop obj) { + return (((uintptr_t) p ^ cast_from_oop(obj)) >> region_size_bytes_shift()) == 0; + } + inline void save_top_before_promote(); inline HeapWord* get_top_before_promote() const { return _top_before_promoted; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.cpp index 6af7548c39ba..bb373a2d97d5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * */ +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" @@ -54,21 +55,24 @@ void ShenandoahSynchronizePinnedRegionStates::synchronize_pin_count(ShenandoahHe } } -ShenandoahFinalMarkUpdateRegionStateClosure::ShenandoahFinalMarkUpdateRegionStateClosure(ShenandoahMarkingContext *ctx) : - _ctx(ctx) { } +ShenandoahFinalMarkUpdateRegionStateClosure::ShenandoahFinalMarkUpdateRegionStateClosure(ShenandoahMarkingContext* ctx, ShenandoahGeneration* generation) : + _ctx(ctx), _generation(generation) { + assert(_ctx != nullptr, "Marking context is required"); + assert(_generation != nullptr, "Generation is required"); +} void ShenandoahFinalMarkUpdateRegionStateClosure::heap_region_do(ShenandoahHeapRegion* r) { + // Region data can only be adjusted for regions in the generation this cycle marked. + // For old regions during a young cycle, we only sync the pin status and update + // the watermark. We cannot reset the TAMS for old regions because we rely on + // that to keep promoted objects alive after old marking is complete. + const bool in_marked_generation = _generation->contains(r); if (r->is_active()) { - if (_ctx != nullptr) { - // _ctx may be null when this closure is used to sync only the pin status - // update the watermark of old regions. For old regions we cannot reset - // the TAMS because we rely on that to keep promoted objects alive after - // old marking is complete. - + if (in_marked_generation) { // All allocations past TAMS are implicitly live, adjust the region data. // Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap. - HeapWord *tams = _ctx->top_at_mark_start(r); - HeapWord *top = r->top(); + HeapWord* tams = _ctx->top_at_mark_start(r); + HeapWord* top = r->top(); if (top > tams) { r->increase_live_data_alloc_words(pointer_delta(top, tams)); } @@ -89,7 +93,7 @@ void ShenandoahFinalMarkUpdateRegionStateClosure::heap_region_do(ShenandoahHeapR } } else { assert(!r->has_live(), "Region %zu should have no live data", r->index()); - assert(_ctx == nullptr || _ctx->top_at_mark_start(r) == r->top(), + assert(!in_marked_generation || _ctx->top_at_mark_start(r) == r->top(), "Region %zu should have correct TAMS", r->index()); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp index 2777b49fafff..a1b348ca7644 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp @@ -94,14 +94,17 @@ class ShenandoahSynchronizePinnedRegionStates : public ShenandoahHeapRegionClosu }; class ShenandoahMarkingContext; +class ShenandoahGeneration; -// Synchronizes region pinned status, sets update watermark and adjust live data tally for regions +// Synchronizes region pinned status, sets update watermark and adjusts live data tally for regions. +// Live data tally is only adjusted for regions in the given generation. class ShenandoahFinalMarkUpdateRegionStateClosure : public ShenandoahHeapRegionClosure { private: ShenandoahMarkingContext* const _ctx; + ShenandoahGeneration* const _generation; ShenandoahSynchronizePinnedRegionStates _pins; public: - explicit ShenandoahFinalMarkUpdateRegionStateClosure(ShenandoahMarkingContext* ctx); + explicit ShenandoahFinalMarkUpdateRegionStateClosure(ShenandoahMarkingContext* ctx, ShenandoahGeneration* generation); void heap_region_do(ShenandoahHeapRegion* r) override; bool is_thread_safe() override { return true; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp index 4a3c2b9f2e30..efea98b61f07 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp @@ -26,11 +26,20 @@ #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahInPlacePromoter.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahScanRemembered.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" +void ShenandoahInPlacePromotionPlanner::RegionPromotionStats::update(ShenandoahHeapRegion* region) { + count++; + usage += region->get_live_data_bytes(); + free += region->free(); + garbage += region->garbage(); +} + ShenandoahInPlacePromotionPlanner::ShenandoahInPlacePromotionPlanner(const ShenandoahGenerationalHeap* heap) : _old_garbage_threshold(ShenandoahHeapRegion::region_size_bytes() * heap->old_generation()->heuristics()->get_old_garbage_threshold() / 100) , _pip_used_threshold(ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage / 100) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp index 4777c1893e3f..b489a591be75 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp @@ -26,7 +26,6 @@ #define SHARE_GC_SHENANDOAH_SHENANDOAHINPLACEPROMOTER_HPP #include "gc/shenandoah/shenandoahFreeSet.hpp" -#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.hpp" class ShenandoahMarkingContext; @@ -82,12 +81,7 @@ class ShenandoahInPlacePromotionPlanner { size_t garbage; RegionPromotionStats() : count(0), usage(0), free(0), garbage(0) {} - void update(ShenandoahHeapRegion* region) { - count++; - usage += region->get_live_data_bytes(); - free += region->free(); - garbage += region->garbage(); - } + void update(ShenandoahHeapRegion* region); }; const size_t _old_garbage_threshold; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp index a2c363b21299..e67acccc8048 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp @@ -50,7 +50,7 @@ class ShenandoahMark: public StackObj { ShenandoahMark(ShenandoahGeneration* generation); public: - template + template ALWAYSINLINE static void mark_through_ref(T* p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp index d1bf28cc33c2..0e19f8fd4b4e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2015, 2022, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "gc/shenandoah/shenandoahMark.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" -#include "gc/shenandoah/shenandoahAgeCensus.hpp" +#include "gc/shenandoah/shenandoahAgeCensus.inline.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" @@ -308,7 +308,7 @@ class ShenandoahSATBBufferClosure : public SATBBufferClosure { assert(size == 0 || !_heap->has_forwarded_objects() || _heap->is_concurrent_old_mark_in_progress(), "Forwarded objects are not expected here"); for (size_t i = 0; i < size; ++i) { oop *p = (oop *) &buffer[i]; - ShenandoahMark::mark_through_ref(p, _queue, _old_queue, _mark_context, false); + ShenandoahMark::mark_through_ref(p, _queue, _old_queue, _mark_context, false); } } }; @@ -317,11 +317,11 @@ template bool ShenandoahMark::in_generation(ShenandoahHeap* const heap, oop obj) { // Each in-line expansion of in_generation() resolves GENERATION at compile time. if (GENERATION == YOUNG) { - return heap->is_in_young(obj); + return heap->has_affiliation(obj, YOUNG_GENERATION); } if (GENERATION == OLD) { - return heap->is_in_old(obj); + return heap->has_affiliation(obj, OLD_GENERATION); } assert((GENERATION == GLOBAL || GENERATION == NON_GEN), "Unexpected generation type"); @@ -329,51 +329,58 @@ bool ShenandoahMark::in_generation(ShenandoahHeap* const heap, oop obj) { return true; } -template +template void ShenandoahMark::mark_through_ref(T *p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak) { + static_assert(GENERATION != NON_GEN, "Should use the non-generational specialization"); + static_assert(!REDIRTY || GENERATION == YOUNG, "Redirty is only valid for young marking"); + // Note: This is a very hot code path, so the code should be conditional on GENERATION template // parameter where possible, in order to generate the most efficient code. - T o = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); + if (CompressedOops::is_null(o)) { + return; + } - ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); - shenandoah_assert_not_forwarded(p, obj); - shenandoah_assert_not_in_cset_except(p, obj, heap->cancelled_gc()); - if (in_generation(heap, obj)) { - mark_ref(q, mark_context, weak, obj); - shenandoah_assert_marked(p, obj); - if (GENERATION == YOUNG && heap->is_in_old(p)) { - // Mark card as dirty because remembered set scanning still finds interesting pointer. - heap->old_generation()->mark_card_as_dirty((HeapWord*)p); - } else if (GENERATION == GLOBAL && heap->is_in_old(p) && heap->is_in_young(obj)) { - // Mark card as dirty because GLOBAL marking finds interesting pointer. - heap->old_generation()->mark_card_as_dirty((HeapWord*)p); - } - } else if (old_q != nullptr) { - // Young mark, bootstrapping old_q or concurrent with old_q marking. - mark_ref(old_q, mark_context, weak, obj); - shenandoah_assert_marked(p, obj); - } else if (GENERATION == OLD) { - // Old mark, found a young pointer. - if (heap->is_in(p)) { - assert(heap->is_in_young(obj), "Expected young object."); - heap->old_generation()->mark_card_as_dirty(p); - } + ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); + oop obj = CompressedOops::decode_not_null(o); + shenandoah_assert_not_forwarded(p, obj); + shenandoah_assert_not_in_cset_except(p, obj, heap->cancelled_gc()); + if (in_generation(heap, obj)) { + mark_ref(q, mark_context, weak, obj); + shenandoah_assert_marked(p, obj); + if (REDIRTY && heap->has_affiliation(p, OLD_GENERATION)) { + // We are redirtying the remembered set, the object iterator + // may visit class metadata that lives outside the heap so we cannot + // assume (or assert) that `p` is in old. + heap->old_generation()->mark_card_as_dirty(p); + } else if (GENERATION == YOUNG && !REDIRTY) { + assert(!heap->has_affiliation(p, OLD_GENERATION), "Young mark should not encounter pointers in old"); + } else if (GENERATION == GLOBAL && heap->is_old_to_young(p, obj)) { + // Mark card as dirty because GLOBAL marking finds interesting pointer. + heap->old_generation()->mark_card_as_dirty(p); + } + } else if (old_q != nullptr) { + // Young mark, bootstrapping old_q or concurrent with old_q marking. + mark_ref(old_q, mark_context, weak, obj); + shenandoah_assert_marked(p, obj); + } else if (GENERATION == OLD) { + // Old mark, found a young pointer. + if (heap->is_in_reserved(p)) { + assert(heap->has_affiliation(obj, YOUNG_GENERATION), "Expected young object."); + heap->old_generation()->mark_card_as_dirty(p); } } } template<> ALWAYSINLINE -void ShenandoahMark::mark_through_ref(oop *p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak) { +void ShenandoahMark::mark_through_ref(oop *p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak) { mark_non_generational_ref(p, q, mark_context, weak); } template<> ALWAYSINLINE -void ShenandoahMark::mark_through_ref(narrowOop *p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak) { +void ShenandoahMark::mark_through_ref(narrowOop *p, ShenandoahObjToScanQueue* q, ShenandoahObjToScanQueue* old_q, ShenandoahMarkingContext* const mark_context, bool weak) { mark_non_generational_ref(p, q, mark_context, weak); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 87629cefb0d4..a23b1a61bce2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -41,8 +41,12 @@ bool ShenandoahMarkingContext::is_bitmap_clear() const { ShenandoahHeap* heap = ShenandoahHeap::heap(); size_t num_regions = heap->num_regions(); for (size_t idx = 0; idx < num_regions; idx++) { + if (heap->is_region_free(idx)) { + continue; + } + ShenandoahHeapRegion* r = heap->get_region(idx); - if (r->is_affiliated() && heap->is_bitmap_slice_committed(r) + if (heap->is_bitmap_slice_committed(r) && !is_bitmap_range_within_region_clear(r->bottom(), r->end())) { return false; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 8d34937218ec..020c66aa1fe6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -452,7 +452,7 @@ void ShenandoahOldGeneration::prepare_regions_and_collection_set(bool concurrent ShenandoahGCPhase phase(concurrent ? ShenandoahPhaseTimings::final_update_region_states : ShenandoahPhaseTimings::degen_gc_final_update_region_states); - ShenandoahFinalMarkUpdateRegionStateClosure cl(complete_marking_context()); + ShenandoahFinalMarkUpdateRegionStateClosure cl(complete_marking_context(), this); parallel_heap_region_iterate(&cl); heap->assert_pinned_region_status(this); @@ -800,7 +800,7 @@ void ShenandoahOldGeneration::clear_cards_for(ShenandoahHeapRegion* region) { _card_scan->mark_range_as_empty(region->bottom(), pointer_delta(region->end(), region->bottom())); } -void ShenandoahOldGeneration::mark_card_as_dirty(void* location) { +void ShenandoahOldGeneration::mark_card_as_dirty(void* location) const { _card_scan->mark_card_as_dirty((HeapWord*)location); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp index 3519303c3037..ba069d961f79 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp @@ -30,10 +30,10 @@ #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" -#include "gc/shenandoah/shenandoahScanRemembered.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" class LogStream; +class ShenandoahScanRemembered; class ShenandoahHeapRegion; class ShenandoahHeapRegionClosure; class ShenandoahOldHeuristics; @@ -193,7 +193,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration { void clear_cards_for(ShenandoahHeapRegion* region); // Mark card for this location as dirty - void mark_card_as_dirty(void* location); + void mark_card_as_dirty(void* location) const; template class ShenandoahHeapRegionLambda : public ShenandoahHeapRegionClosure { @@ -343,7 +343,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration { size_t usage_trigger_threshold() const; - bool can_start_gc() { + bool can_start_gc() const { return _state == IDLE; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index c24735b92cf4..835d141df950 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021, Red Hat, Inc. and/or its affiliates. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,6 +26,7 @@ #include "classfile/javaClasses.hpp" #include "gc/shared/workerThread.hpp" +#include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" @@ -64,7 +65,7 @@ static void card_mark_barrier(T* field, oop value) { assert(ShenandoahCardBarrier, "Card-mark barrier should be on"); ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); assert(heap->is_in_or_null(value), "Should be in heap"); - if (heap->is_in_old(field) && heap->is_in_young(value)) { + if (heap->is_old_to_young(field, value)) { // For Shenandoah, each generation collects all the _referents_ that belong to the // collected generation. We can end up with discovered lists that contain a mixture // of old and young _references_. These references are linked together through the @@ -97,7 +98,7 @@ void set_oop_field(narrowOop* field, oop value) { static oop lrb(oop obj) { if (obj != nullptr && ShenandoahHeap::heap()->marking_context()->is_marked(obj)) { - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(obj); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, obj, (oop*)nullptr); } else { return obj; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp index 00910d3035ed..e921de34d1c9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp @@ -40,59 +40,59 @@ JRT_END JRT_LEAF(void, ShenandoahRuntime::write_barrier_pre(oopDesc* obj)) // Called from barrier slow-paths on full buffer. // We need to enqueue without filters to force buffer cleanups. - ShenandoahBarrierSet::barrier_set()->enqueue(obj, /* filter = */ false); + ShenandoahBarrierSet::barrier_set()->keepalive_barrier(ON_STRONG_OOP_REF, (oop*)nullptr, obj, ShenandoahBarrierSet::FILTER_NONE); JRT_END JRT_LEAF(void, ShenandoahRuntime::write_barrier_pre_narrow(narrowOop nobj)) assert(!CompressedOops::is_null(nobj), "Filtered by caller"); + oop obj = CompressedOops::decode_not_null(nobj); // Called from barrier slow-paths on full buffer. // We need to enqueue without filters to force buffer cleanups. - oop obj = CompressedOops::decode_not_null(nobj); - ShenandoahBarrierSet::barrier_set()->enqueue(obj, /* filter = */ false); + ShenandoahBarrierSet::barrier_set()->keepalive_barrier(ON_STRONG_OOP_REF, (oop*)nullptr, obj, ShenandoahBarrierSet::FILTER_NONE); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_strong(oopDesc* src, oop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, src, load_addr); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_strong_narrow(oopDesc* src, narrowOop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, src, load_addr); JRT_END JRT_LEAF(narrowOop, ShenandoahRuntime::load_reference_barrier_strong_narrow_narrow(narrowOop src, narrowOop* load_addr)) assert(!CompressedOops::is_null(src), "Filtered by caller"); oop s = CompressedOops::decode_not_null(src); - oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(s, load_addr); + oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, s, load_addr); return CompressedOops::encode_not_null(r); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak(oopDesc* src, oop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_WEAK_OOP_REF, src, load_addr); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak_narrow(oopDesc* src, narrowOop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_WEAK_OOP_REF, src, load_addr); JRT_END JRT_LEAF(narrowOop, ShenandoahRuntime::load_reference_barrier_weak_narrow_narrow(narrowOop src, narrowOop* load_addr)) assert(!CompressedOops::is_null(src), "Filtered by caller"); oop s = CompressedOops::decode_not_null(src); - oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(s, load_addr); + oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_WEAK_OOP_REF, s, load_addr); return CompressedOops::encode(r); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom(oopDesc* src, oop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, src, load_addr); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom_narrow(oopDesc* src, narrowOop* load_addr)) - return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); + return ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, src, load_addr); JRT_END JRT_LEAF(narrowOop, ShenandoahRuntime::load_reference_barrier_phantom_narrow_narrow(narrowOop src, narrowOop* load_addr)) assert(!CompressedOops::is_null(src), "Filtered by caller"); oop s = CompressedOops::decode_not_null(src); - oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(s, load_addr); + oop r = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, s, load_addr); return CompressedOops::encode(r); JRT_END diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index c3a82b987e22..57899154ff73 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,12 +108,6 @@ bool ShenandoahDirectCardMarkRememberedSet::is_write_card_dirty(HeapWord* p) con return (bp[0] == CardTable::dirty_card_val()); } -void ShenandoahDirectCardMarkRememberedSet::mark_card_as_dirty(HeapWord* p) { - size_t index = card_index_for_addr(p); - CardValue* bp = &(_card_table->write_byte_map())[index]; - bp[0] = CardTable::dirty_card_val(); -} - void ShenandoahDirectCardMarkRememberedSet::mark_range_as_dirty(HeapWord* p, size_t num_heap_words) { CardValue* bp = &(_card_table->write_byte_map_base())[uintptr_t(p) >> _card_shift]; CardValue* end_bp = &(_card_table->write_byte_map_base())[uintptr_t(p + num_heap_words) >> _card_shift]; @@ -232,7 +226,7 @@ void ShenandoahCardCluster::update_card_table(HeapWord* start, HeapWord* end) { previous_address = address; const oop obj = cast_to_oop(address); - address += obj->size(); + address += ShenandoahForwarding::size(obj); } // Register the last object seen in this range. @@ -351,7 +345,7 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con if (prev < left) { oop obj = cast_to_oop(prev); assert(oopDesc::is_oop(obj), "Should be an object"); - HeapWord* obj_end = prev + obj->size(); + HeapWord* obj_end = prev + ShenandoahForwarding::size(obj); if (obj_end > left) { return prev; } @@ -403,7 +397,7 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con if (ctx->is_marked(p)) { oop obj = cast_to_oop(p); assert(oopDesc::is_oop(obj), "Should be an object"); - assert(p + obj->size() > left, "This object should span start of card"); + assert(p + ShenandoahForwarding::size(obj) > left, "This object should span start of card"); assert(p < right, "Result must precede right"); return p; } else { @@ -449,7 +443,7 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con #ifdef ASSERT oop obj = cast_to_oop(p); assert(oopDesc::is_oop(obj), "Should be an object"); - assert(p + obj->size() > left, "obj should end after left end of card"); + assert(p + ShenandoahForwarding::size(obj) > left, "obj should end after left end of card"); #endif // ASSERT return p; } @@ -474,10 +468,6 @@ bool ShenandoahScanRemembered::is_card_dirty(HeapWord* p) { return _rs->is_card_dirty(p); } -void ShenandoahScanRemembered::mark_card_as_dirty(HeapWord* p) { - _rs->mark_card_as_dirty(p); -} - bool ShenandoahScanRemembered::is_write_card_dirty(HeapWord* p) { return _rs->is_write_card_dirty(p); } @@ -524,7 +514,7 @@ bool ShenandoahScanRemembered::verify_registration(HeapWord* address, Shenandoah while (base_addr + offset < address) { oop obj = cast_to_oop(base_addr + offset); if (!ctx || ctx->is_marked(obj)) { - offset += obj->size(); + offset += ShenandoahForwarding::size(obj); } else { // If this object is not live, don't trust its size(); all objects above tams are live. ShenandoahHeapRegion* r = heap->heap_region_containing(obj); @@ -553,7 +543,7 @@ bool ShenandoahScanRemembered::verify_registration(HeapWord* address, Shenandoah do { oop obj = cast_to_oop(base_addr + offset); prev_offset = offset; - offset += obj->size(); + offset += ShenandoahForwarding::size(obj); } while (offset < max_offset); if (_scc->get_last_start(index) != prev_offset) { return false; @@ -592,7 +582,7 @@ bool ShenandoahScanRemembered::verify_registration(HeapWord* address, Shenandoah oop obj = cast_to_oop(base_addr + offset); if (ctx->is_marked(obj)) { prev_offset = offset; - offset += obj->size(); + offset += ShenandoahForwarding::size(obj); last_obj = obj; } else { offset = ctx->get_next_marked_addr(base_addr + offset, tams) - base_addr; @@ -602,7 +592,7 @@ bool ShenandoahScanRemembered::verify_registration(HeapWord* address, Shenandoah // by consulting the size() fields of each. } } while (offset < max_offset); - if (last_obj != nullptr && prev_offset + last_obj->size() >= max_offset) { + if (last_obj != nullptr && prev_offset + ShenandoahForwarding::size(last_obj) >= max_offset) { // last marked object extends beyond end of card if (_scc->get_last_start(index) != prev_offset) { return false; @@ -640,8 +630,12 @@ void ShenandoahScanRemembered::roots_do(OopIterateClosure* cl) { bool old_bitmap_stable = heap->old_generation()->is_mark_complete(); log_debug(gc, remset)("Scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); for (size_t i = 0, n = heap->num_regions(); i < n; ++i) { + if (!heap->is_region_old(i)) { + continue; + } + ShenandoahHeapRegion* region = heap->get_region(i); - if (region->is_old() && region->is_active() && !region->is_cset()) { + if (region->is_active() && !region->is_cset()) { HeapWord* start_of_range = region->bottom(); HeapWord* end_of_range = region->top(); size_t start_cluster_no = cluster_for_addr(start_of_range); @@ -812,7 +806,7 @@ void ShenandoahScanRememberedTask::do_work(uint worker_id) { ShenandoahObjToScanQueue* q = _queue_set->queue(worker_id); ShenandoahObjToScanQueue* old = _old_queue_set == nullptr ? nullptr : _old_queue_set->queue(worker_id); - ShenandoahMarkRefsClosure cl(q, _rp, old); + ShenandoahRedirtyCardsMarkClosure cl(q, _rp, old); ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); ShenandoahScanRemembered* scanner = heap->old_generation()->card_scan(); @@ -1084,7 +1078,7 @@ void ShenandoahReconstructRememberedSetTask::work(uint worker_id) { if (r->is_humongous_start()) { // First, clear the remembered set oop obj = cast_to_oop(obj_addr); - size_t size = obj->size(); + size_t size = ShenandoahForwarding::size(obj); size_t num_regions = ShenandoahHeapRegion::required_regions(size * HeapWordSize); size_t region_index = r->index(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp index 244ed7edd4c6..989c0b9c0fd5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp @@ -172,6 +172,7 @@ // These limitations will be addressed in future enhancements to the // existing implementation. +#include "gc/shared/gc_globals.hpp" #include "gc/shared/workerThread.hpp" #include "gc/shenandoah/shenandoahCardStats.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" @@ -235,7 +236,8 @@ class ShenandoahDirectCardMarkRememberedSet: public CHeapObj { inline void mark_range_as_dirty(size_t card_index, size_t num_cards); inline bool is_card_dirty(HeapWord* p) const; inline bool is_write_card_dirty(HeapWord* p) const; - inline void mark_card_as_dirty(HeapWord* p); + inline void mark_card_as_dirty(HeapWord* p) const; + inline void mark_range_as_dirty(HeapWord* p, size_t num_heap_words); inline void mark_range_as_clean(HeapWord* p, size_t num_heap_words); @@ -367,9 +369,7 @@ class ShenandoahCardCluster: public CHeapObj { static const uint8_t FirstStartBits = 0x7f; // Check that we have enough bits to store the largest possible offset into a card for an object start. - // The value for maximum card size is based on the constraints for GCCardSizeInBytes in gc_globals.hpp. - static const int MaxCardSize = NOT_LP64(512) LP64_ONLY(1024); - STATIC_ASSERT((MaxCardSize / HeapWordSize) - 1 <= FirstStartBits); + STATIC_ASSERT((MaxGCCardSizeInBytes / HeapWordSize) - 1 <= FirstStartBits); crossing_info* _object_starts; @@ -782,7 +782,8 @@ class ShenandoahScanRemembered: public CHeapObj { bool is_write_card_dirty(size_t card_index); bool is_card_dirty(HeapWord* p); bool is_write_card_dirty(HeapWord* p); - void mark_card_as_dirty(HeapWord* p); + inline void mark_card_as_dirty(HeapWord* p) const; + void mark_range_as_dirty(HeapWord* p, size_t num_heap_words); void mark_range_as_clean(HeapWord* p, size_t num_heap_words); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index 0948b737c776..64624faeb7d2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,6 @@ #include "gc/shenandoah/shenandoahScanRemembered.hpp" -#include "gc/shared/collectorCounters.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahCardStats.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" @@ -37,9 +35,12 @@ #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "logging/log.hpp" #include "memory/iterator.hpp" -#include "oops/objArrayOop.hpp" #include "oops/oop.hpp" +void ShenandoahScanRemembered::mark_card_as_dirty(HeapWord* p) const { + _rs->mark_card_as_dirty(p); +} + // Process all objects starting within count clusters beginning with first_cluster and for which the start address is // less than end_of_range. For any non-array object whose header lies on a dirty card, scan the entire object, // even if its end reaches beyond end_of_range. Object arrays, on the other hand, are precisely dirtied and @@ -427,4 +428,10 @@ inline bool ShenandoahRegionChunkIterator::next(struct ShenandoahRegionChunk *as return true; } +void ShenandoahDirectCardMarkRememberedSet::mark_card_as_dirty(HeapWord* p) const { + size_t index = card_index_for_addr(p); + CardValue* bp = &(_card_table->write_byte_map())[index]; + bp[0] = CardTable::dirty_card_val(); +} + #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSCANREMEMBEREDINLINE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp index 7bdf2d273498..486a84f204ff 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp @@ -62,6 +62,9 @@ class BufferedOverflowTaskQueue: public OverflowTaskQueue return _buf_empty && taskqueue_t::is_empty(); } + NOINLINE + void pop_more_overflow(); + private: bool _buf_empty; E _elem; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.inline.hpp index 0f01425f3e9f..6c070564af00 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.inline.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2019, Red Hat, Inc. All rights reserved. - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,29 @@ bool BufferedOverflowTaskQueue::pop(E &t) { return true; } - return taskqueue_t::pop_overflow(t); + if (taskqueue_t::pop_overflow(t)) { + pop_more_overflow(); + return true; + } + + return false; +} + +template +void BufferedOverflowTaskQueue::pop_more_overflow() { + // Local queue is empty and we have overflow. Overflow queue is invisible + // for work stealing, so we want to transfer as much as practically possible + // from it. Pulling too little hinders work balancing. Pulling too much + // incurs stalls (important e.g. when we need to respond to yield/cancellation). + // Local queues must also have some space left for local pushes. + constexpr uint fill = MIN2(16*K, N/2); + + E tmp; + assert(taskqueue_t::size() == 0, "Local queue is empty"); + for (uint i = 0; (i < fill) && taskqueue_t::pop_overflow(tmp); i++) { + bool pushed = taskqueue_t::try_push_to_taskqueue(tmp); + assert(pushed, "Should always succeed pushing"); + } } template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 19c33c77b26b..be24582de915 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2017, 2025, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ */ #include "gc/shared/tlab_globals.hpp" +#include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahForwarding.inline.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" @@ -1440,8 +1441,12 @@ void ShenandoahVerifier::verify_rem_set_before_mark() { ShenandoahScanRemembered* scanner = old_generation->card_scan(); for (size_t i = 0, n = _heap->num_regions(); i < n; ++i) { + if (!_heap->is_region_old(i)) { + continue; + } + ShenandoahHeapRegion* r = _heap->get_region(i); - if (r->is_old() && r->is_active()) { + if (r->is_active()) { help_verify_region_rem_set(scanner, r, r->end(), "Verify init-mark remembered set violation"); } } @@ -1453,8 +1458,12 @@ void ShenandoahVerifier::verify_rem_set_after_full_gc() { ShenandoahWriteTableScanner scanner(ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()); for (size_t i = 0, n = _heap->num_regions(); i < n; ++i) { + if (!_heap->is_region_old(i)) { + continue; + } + ShenandoahHeapRegion* r = _heap->get_region(i); - if (r->is_old() && !r->is_cset()) { + if (!r->is_cset()) { help_verify_region_rem_set(&scanner, r, r->top(), "Remembered set violation at end of Full GC"); } } @@ -1470,8 +1479,12 @@ void ShenandoahVerifier::verify_rem_set_before_update_ref() { ShenandoahWriteTableScanner scanner(_heap->old_generation()->card_scan()); for (size_t i = 0, n = _heap->num_regions(); i < n; ++i) { + if (!_heap->is_region_old(i)) { + continue; + } + ShenandoahHeapRegion* r = _heap->get_region(i); - if (r->is_old() && !r->is_cset()) { + if (!r->is_cset()) { help_verify_region_rem_set(&scanner, r, r->get_update_watermark(), "Remembered set violation at init-update-references"); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index d76348b030aa..e57884548361 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -275,6 +275,7 @@ "margin of error for the average cycle time and average " \ "allocation rate. Increasing this value will cause the " \ "heuristic to initiate more concurrent cycles." ) \ + range(0.319,3.291) \ \ product(uintx, ShenandoahGuaranteedGCInterval, 5*60*1000, EXPERIMENTAL, \ "Many heuristics would guarantee a concurrent GC cycle at " \ diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index 6c82f388aae6..7d732347c296 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -320,7 +320,7 @@ void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const { stubs->at(i)->emit_code(masm); } - masm.flush(); + // Code will be copied. No ICache sync required. } int ZBarrierSetC2::estimate_stub_size() const { diff --git a/src/hotspot/share/gc/z/zMarkingSMR.cpp b/src/hotspot/share/gc/z/zMarkingSMR.cpp index 0f45f1746677..35e9af34a7b9 100644 --- a/src/hotspot/share/gc/z/zMarkingSMR.cpp +++ b/src/hotspot/share/gc/z/zMarkingSMR.cpp @@ -66,6 +66,9 @@ void ZMarkingSMR::free_node(ZMarkStackListNode* node) { return; } + // Order the hazard pointers loads w.r.t. the unlinking of the head node. + OrderAccess::fence(); + ZPerWorkerIterator iter(&_worker_states); ZArray* const scanned_hazards = &local_state->_scanned_hazards; diff --git a/src/hotspot/share/interpreter/interpreter.cpp b/src/hotspot/share/interpreter/interpreter.cpp index 1f327152e0c6..a3850a5eab41 100644 --- a/src/hotspot/share/interpreter/interpreter.cpp +++ b/src/hotspot/share/interpreter/interpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ CodeletMark::~CodeletMark() { // Align so printing shows nop's instead of random code at the end (Codelets are aligned). (*_masm)->align(wordSize); // Make sure all code is in code buffer. - (*_masm)->flush(); + (*_masm)->invalidate_icache(); // Commit Codelet. int committed_code_size = (*_masm)->code()->pure_insts_size(); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 37368279f5cf..f081d7d0968d 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -798,14 +798,6 @@ JRT_END JRT_LEAF(void, InterpreterRuntime::monitorexit(BasicObjectLock* elem)) oop obj = elem->obj(); assert(Universe::heap()->is_in(obj), "must be an object"); - // 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()) { - if (CheckJNICalls) { - fatal("Object has been unlocked by JNI"); - } - return; - } ObjectSynchronizer::exit(obj, elem->lock(), JavaThread::current()); // Free entry. If it is not cleared, the exception handling code will try to unlock the monitor // again at method exit or in the case of an exception. diff --git a/src/hotspot/share/interpreter/rewriter.cpp b/src/hotspot/share/interpreter/rewriter.cpp index f6422e123c40..1353fda40c59 100644 --- a/src/hotspot/share/interpreter/rewriter.cpp +++ b/src/hotspot/share/interpreter/rewriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * 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,8 +109,10 @@ void Rewriter::make_constant_pool_cache(TRAPS) { assert(_field_entry_index == _initialized_field_entries.length(), "Field entry size mismatch"); assert(_method_entry_index == _initialized_method_entries.length(), "Method entry size mismatch"); ConstantPoolCache* cache = - ConstantPoolCache::allocate(loader_data, _invokedynamic_references_map, - _initialized_indy_entries, _initialized_field_entries, _initialized_method_entries, + ConstantPoolCache::allocate(loader_data, + _initialized_indy_entries, + _initialized_field_entries, + _initialized_method_entries, CHECK); // initialize object cache in constant pool @@ -255,14 +257,14 @@ void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_i MethodHandles::is_signature_polymorphic_name(vmClasses::MethodHandle_klass(), _pool->uncached_name_ref_at(cp_index))) { // we may need a resolved_refs entry for the appendix - int resolved_index = add_invokedynamic_resolved_references_entry(cp_index, cache_index); + int resolved_index = add_invokedynamic_resolved_references_entry(cp_index); _initialized_method_entries.at(cache_index).set_resolved_references_index((u2)resolved_index); status = +1; } else if (_pool->uncached_klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_VarHandle() && MethodHandles::is_signature_polymorphic_name(vmClasses::VarHandle_klass(), _pool->uncached_name_ref_at(cp_index))) { // we may need a resolved_refs entry for the appendix - int resolved_index = add_invokedynamic_resolved_references_entry(cp_index, cache_index); + int resolved_index = add_invokedynamic_resolved_references_entry(cp_index); _initialized_method_entries.at(cache_index).set_resolved_references_index((u2)resolved_index); status = +1; } else { @@ -294,7 +296,7 @@ void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) { assert(p[-1] == Bytecodes::_invokedynamic, "not invokedynamic bytecode"); if (!reverse) { int cp_index = Bytes::get_Java_u2(p); - int resolved_index = add_invokedynamic_resolved_references_entry(cp_index, -1); // Indy no longer has a CPCE + int resolved_index = add_invokedynamic_resolved_references_entry(cp_index); // Indy no longer has a CPCE // Replace the trailing four bytes with an index to the array of // indy resolution information in the CPC. There is one entry for // each bytecode, even if they make the same call. In other words, @@ -584,7 +586,6 @@ Rewriter::Rewriter(InstanceKlass* klass, const constantPoolHandle& cpool, Array< _cp_map(cpool->length()), _reference_map(cpool->length()), _resolved_references_map(cpool->length() / 2), - _invokedynamic_references_map(cpool->length() / 2), _method_handle_invokers(cpool->length()), _invokedynamic_index(0), _field_entry_index(0), diff --git a/src/hotspot/share/interpreter/rewriter.hpp b/src/hotspot/share/interpreter/rewriter.hpp index 92e8e7db5346..0da02dd09074 100644 --- a/src/hotspot/share/interpreter/rewriter.hpp +++ b/src/hotspot/share/interpreter/rewriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ class Rewriter: public StackObj { GrowableArray _cp_map; GrowableArray _reference_map; // maps from cp index to resolved_refs index (or -1) GrowableArray _resolved_references_map; // for strings, methodHandle, methodType - GrowableArray _invokedynamic_references_map; // for invokedynamic resolved refs GrowableArray _method_handle_invokers; int _resolved_reference_limit; int _invokedynamic_index; @@ -68,7 +67,6 @@ class Rewriter: public StackObj { _method_handle_invokers.trunc_to(0); _resolved_references_map.trunc_to(0); - _invokedynamic_references_map.trunc_to(0); _resolved_reference_limit = -1; } @@ -101,13 +99,10 @@ class Rewriter: public StackObj { } // add a new entry to the resolved_references map (for invokedynamic and invokehandle only) - int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) { + int add_invokedynamic_resolved_references_entry(int cp_index) { assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration"); int ref_index = _resolved_references_map.append(cp_index); // many-to-one assert(ref_index >= _resolved_reference_limit, ""); - if (_pool->tag_at(cp_index).value() != JVM_CONSTANT_InvokeDynamic) { - _invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1); - } return ref_index; } diff --git a/src/hotspot/share/interpreter/templateTable.cpp b/src/hotspot/share/interpreter/templateTable.cpp index 48845511f18e..688c87a10b71 100644 --- a/src/hotspot/share/interpreter/templateTable.cpp +++ b/src/hotspot/share/interpreter/templateTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ void Template::generate(InterpreterMacroAssembler* masm) { TemplateTable::_masm = masm; // code generation _gen(_arg); - masm->flush(); + masm->invalidate_icache(); } diff --git a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp index ed478509f1f4..1c7fc571e65c 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp @@ -97,8 +97,9 @@ InstanceKlass* JfrClassTransformer::create_instance_klass(InstanceKlass*& ik, Cl void JfrClassTransformer::copy_traceid(const InstanceKlass* ik, const InstanceKlass* new_ik) { assert(ik != nullptr, "invariant"); assert(new_ik != nullptr, "invariant"); + assert(new_ik->trace_id() == 0, "invariant"); new_ik->set_trace_id(ik->trace_id()); - assert(TRACE_ID(ik) == TRACE_ID(new_ik), "invariant"); + ik->set_trace_id(0); } InstanceKlass* JfrClassTransformer::create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPS) { @@ -179,7 +180,8 @@ void JfrClassTransformer::rewrite_klass_pointer(InstanceKlass*& ik, InstanceKlas assert(ik != nullptr, "invariant"); assert(new_ik != nullptr, "invariant"); assert(thread != nullptr, "invariant"); - assert(TRACE_ID(ik) == TRACE_ID(new_ik), "invariant"); + assert(TRACE_ID(ik) == 0, "invariant"); + assert(TRACE_ID(ik) != TRACE_ID(new_ik), "invariant"); assert(!thread->has_pending_exception(), "invariant"); // Assign original InstanceKlass* back onto "its" parser object for proper destruction. parser.set_klass_to_deallocate(ik); diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp index b30f80d23b7b..cc0146c52536 100644 --- a/src/hotspot/share/jfr/jfr.cpp +++ b/src/hotspot/share/jfr/jfr.cpp @@ -28,6 +28,7 @@ #include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/leakprofiler/leakProfiler.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" +#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/repository/jfrEmergencyDump.hpp" #include "jfr/recorder/repository/jfrRepository.hpp" @@ -35,6 +36,7 @@ #include "jfr/recorder/service/jfrRecorderService.hpp" #include "jfr/support/jfrClassDefineEvent.hpp" #include "jfr/support/jfrKlassExtension.hpp" +#include "jfr/support/jfrKlassUnloading.hpp" #include "jfr/support/jfrResolution.hpp" #include "jfr/support/jfrThreadLocal.hpp" #include "jfr/support/methodtracer/jfrMethodTracer.hpp" @@ -43,7 +45,7 @@ #include "oops/klass.hpp" #include "runtime/java.hpp" #include "runtime/javaThread.hpp" - +#include "runtime/safepoint.hpp" bool Jfr::is_enabled() { return JfrRecorder::is_enabled(); @@ -175,6 +177,26 @@ void Jfr::on_report_java_out_of_memory() { } } +void Jfr::on_definition(const InstanceKlass* ik, JavaThread* jt) { + const bool from_boot_loader_modules_image = JfrTraceId::has_preload_bootloader_bit(ik); + if (from_boot_loader_modules_image) { + JfrTraceId::clear_preload_bootloader_bit(ik); + } + if (JfrTraceId::has_preload_sticky_bit(ik)) { + assert(JfrMethodTracer::in_use(), "invariant"); + JfrMethodTracer::on_definition(ik, jt); + } + JfrClassDefineEvent::send_event(ik, from_boot_loader_modules_image, jt); +} + +void Jfr::on_deallocation(const Klass* k) { + assert(k != nullptr, "invariant"); + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); + if (JfrMethodTracer::in_use() && JfrTraceId::has_sticky_bit(k)) { + JfrKlassUnloading::add_to_unloaded_set(k); + } +} + #if INCLUDE_CDS void Jfr::on_restoration(const Klass* k, JavaThread* jt) { assert(k != nullptr, "invariant"); diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp index ac6a232dda1b..e1bc6834a18f 100644 --- a/src/hotspot/share/jfr/jfr.hpp +++ b/src/hotspot/share/jfr/jfr.hpp @@ -80,6 +80,8 @@ class Jfr : AllStatic { static bool has_sample_request(JavaThread* jt); static void check_and_process_sample_request(JavaThread* jt); static void on_report_java_out_of_memory(); + static void on_definition(const InstanceKlass* ik, JavaThread* jt); + static void on_deallocation(const Klass* k); CDS_ONLY(static void on_restoration(const Klass* k, JavaThread* jt);) }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index c1eded10f92b..3fd15d9aed4a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -38,7 +38,6 @@ #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp" #include "jfr/recorder/storage/jfrReferenceCountedStorage.hpp" #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" -#include "jfr/recorder/stringpool/jfrStringPool.hpp" #include "jfr/support/jfrDeprecationManager.hpp" #include "jfr/support/jfrKlassUnloading.hpp" #include "jfr/support/jfrThreadLocal.hpp" @@ -507,7 +506,6 @@ void JfrCheckpointManager::shift_epoch() { DEBUG_ONLY(const u1 current_epoch = JfrTraceIdEpoch::current();) JfrTraceIdEpoch::shift_epoch(); assert(current_epoch != JfrTraceIdEpoch::current(), "invariant"); - JfrStringPool::on_epoch_shift(); } size_t JfrCheckpointManager::write() { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp index 405fa25baff6..0715ad87b9c0 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -292,3 +292,10 @@ void JfrTraceId::untag_jdk_jfr_event_sub(const Klass* k) { } assert(IS_NOT_AN_EVENT_SUB_KLASS(k), "invariant"); } + +#ifdef ASSERT +traceid JfrTraceId::preload_bits(const Klass* k) { + assert(k != nullptr, "invariant"); + return PRELOAD_TAG_BITS_OF(k); +} +#endif diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp index f10782be0eab..0c95fd7c5a71 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,8 +146,20 @@ class JfrTraceId : public AllStatic { static void set_sticky_bit(const Method* method); static void clear_sticky_bit(const Klass* k); static void clear_sticky_bit(const Method* method); - static bool has_timing_bit(const InstanceKlass* scratch_klass); - static void set_timing_bit(const InstanceKlass* scratch_klass); + static bool has_timing_bit(const InstanceKlass* ik); + static void set_timing_bit(const InstanceKlass* ik); + static void clear_timing_bit(const InstanceKlass* ik); + + // Preload tag bits (only valid during class loading, before a klass is defined) + static bool has_preload_sticky_bit(const Klass* k); + static void set_preload_sticky_bit(const Klass* k); + static void clear_preload_sticky_bit(const Klass* k); + + static bool has_preload_bootloader_bit(const Klass* k); + static void set_preload_bootloader_bit(const Klass* k); + static void clear_preload_bootloader_bit(const Klass* k); + + DEBUG_ONLY(static traceid preload_bits(const Klass* k);) }; #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp index 2af1080820f4..e37e08d090f6 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -209,16 +209,64 @@ inline void JfrTraceId::clear_sticky_bit(const Method* method) { assert(!JfrTraceId::has_sticky_bit(method), "invariant"); } -inline bool JfrTraceId::has_timing_bit(const InstanceKlass* scratch_klass) { - assert(scratch_klass != nullptr, "invariant"); - return HAS_TIMING_BIT(scratch_klass); +inline bool JfrTraceId::has_timing_bit(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + return HAS_TIMING_BIT(ik); +} + +inline void JfrTraceId::set_timing_bit(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(!has_timing_bit(ik), "invariant"); + SET_TIMING_BIT(ik); + assert(has_timing_bit(ik), "invariant"); +} + +inline void JfrTraceId::clear_timing_bit(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(has_timing_bit(ik), "invariant"); + CLEAR_TIMING_BIT(ik); + assert(!has_timing_bit(ik), "invariant"); +} + +inline bool JfrTraceId::has_preload_sticky_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + return HAS_PRELOAD_TAG_BIT_STICKY(k); } -inline void JfrTraceId::set_timing_bit(const InstanceKlass* scratch_klass) { - assert(scratch_klass != nullptr, "invariant"); - assert(!has_timing_bit(scratch_klass), "invariant"); - SET_TIMING_BIT(scratch_klass); - assert(has_timing_bit(scratch_klass), "invariant"); +inline void JfrTraceId::set_preload_sticky_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + assert(!has_preload_sticky_bit(k), "invariant"); + SET_PRELOAD_TAG_BIT_STICKY(k); + assert(has_preload_sticky_bit(k), "invariant"); +} + +inline void JfrTraceId::clear_preload_sticky_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + assert(has_preload_sticky_bit(k), "invariant"); + CLEAR_PRELOAD_TAG_BIT_STICKY(k); + assert(!has_preload_sticky_bit(k), "invariant"); +} + +inline bool JfrTraceId::has_preload_bootloader_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + return HAS_PRELOAD_TAG_BIT_BOOTLOADER(k); +} + +inline void JfrTraceId::set_preload_bootloader_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + assert(!has_preload_bootloader_bit(k), "invariant"); + SET_PRELOAD_TAG_BIT_BOOTLOADER(k); + assert(has_preload_bootloader_bit(k), "invariant"); +} + +inline void JfrTraceId::clear_preload_bootloader_bit(const Klass* k) { + assert(k != nullptr, "invariant"); + assert(has_preload_bootloader_bit(k), "invariant"); + CLEAR_PRELOAD_TAG_BIT_BOOTLOADER(k); + assert(!has_preload_bootloader_bit(k), "invariant"); } #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp index 27cf66cc1fe7..10ab11dde99f 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,12 @@ #define TAG_BITS (EPOCH_1_METHOD_BIT | EPOCH_0_METHOD_BIT | EPOCH_1_BIT | EPOCH_0_BIT) #define ALL_BITS (META_BITS | EVENT_BITS | TAG_BITS) #define ALL_BITS_MASK (~(ALL_BITS)) +#define PRELOAD_TAG_BIT_STICKY (EPOCH_1_METHOD_BIT) +#define PRELOAD_TAG_BIT_STICKY_MASK (~(PRELOAD_TAG_BIT_STICKY)) +#define PRELOAD_TAG_BIT_BOOTLOADER (EPOCH_0_METHOD_BIT) +#define PRELOAD_TAG_BIT_BOOTLOADER_MASK (~(PRELOAD_TAG_BIT_BOOTLOADER)) +#define PRELOAD_TAG_BITS (PRELOAD_TAG_BIT_STICKY | PRELOAD_TAG_BIT_BOOTLOADER) +#define PRELOAD_TAG_BITS_CLEAR_MASK (~(PRELOAD_TAG_BITS)) // epoch relative bits #define THIS_EPOCH_BIT (JfrTraceIdEpoch::this_epoch_bit()) @@ -78,19 +84,21 @@ // operators #define TRACE_ID_RAW(ptr) (JfrTraceIdBits::load(ptr)) #define TRACE_ID(ptr) (TRACE_ID_RAW(ptr) >> TRACE_ID_SHIFT) -#define TRACE_ID_MASKED(ptr) (TRACE_ID_RAW(ptr) & ALL_BITS_MASK) +#define TRACE_ID_MASKED(ptr, mask) (TRACE_ID_RAW(ptr) & mask) +#define TRACE_ID_MASKED_ALL_BITS(ptr) (TRACE_ID_MASKED(ptr, ALL_BITS_MASK)) #define TRACE_ID_PREDICATE(ptr, bits) ((TRACE_ID_RAW(ptr) & bits) != 0) #define TRACE_ID_TAG(ptr, bits) (JfrTraceIdBits::store(bits, ptr)) #define TRACE_ID_TAG_CAS(ptr, bits) (JfrTraceIdBits::cas(bits, ptr)) #define TRACE_ID_MASK_CLEAR(ptr, mask) (JfrTraceIdBits::mask_store(mask, ptr)) #define TRACE_ID_META_TAG(ptr, bits) (JfrTraceIdBits::meta_store(bits, ptr)) #define TRACE_ID_META_MASK_CLEAR(ptr, mask) (JfrTraceIdBits::meta_mask_store(mask, ptr)) -#define METHOD_ID(kls, method) (TRACE_ID_MASKED(kls) | (method)->orig_method_idnum()) +#define METHOD_ID(kls, method) (TRACE_ID_MASKED_ALL_BITS(kls) | (method)->orig_method_idnum()) #define METHOD_FLAG_PREDICATE(method, bits) ((method)->is_trace_flag_set(bits)) #define METHOD_FLAG_TAG(method, bits) (JfrTraceIdBits::store(bits, method)) #define METHOD_META_TAG(method, bits) (JfrTraceIdBits::meta_store(bits, method)) #define METHOD_FLAG_CLEAR(method, bits) (JfrTraceIdBits::clear_cas(bits, method)) #define METHOD_META_MASK_CLEAR(method, mask) (JfrTraceIdBits::meta_mask_store(mask, method)) +#define PRELOAD_TAG_BITS_OF(ptr) (TRACE_ID_MASKED(ptr, PRELOAD_TAG_BITS)) // predicates #define USED_THIS_EPOCH(ptr) (TRACE_ID_PREDICATE(ptr, (STICKY_BIT | TRANSIENT_BIT | THIS_EPOCH_BIT))) @@ -110,6 +118,8 @@ #define METHOD_FLAG_USED_PREVIOUS_EPOCH_BIT(method) (METHOD_FLAG_PREDICATE(method, (PREVIOUS_EPOCH_BIT))) #define METHOD_FLAG_NOT_USED_PREVIOUS_EPOCH(method) (!(METHOD_FLAG_USED_PREVIOUS_EPOCH(method))) #define IS_METHOD_BLESSED(method) (METHOD_FLAG_PREDICATE(method, BLESSED_METHOD_BIT)) +#define HAS_PRELOAD_TAG_BIT_STICKY(ptr) (TRACE_ID_PREDICATE(ptr, PRELOAD_TAG_BIT_STICKY)) +#define HAS_PRELOAD_TAG_BIT_BOOTLOADER(ptr) (TRACE_ID_PREDICATE(ptr, PRELOAD_TAG_BIT_BOOTLOADER)) // setters #define SET_USED_THIS_EPOCH(ptr) (TRACE_ID_TAG(ptr, THIS_EPOCH_BIT)) @@ -119,6 +129,10 @@ #define CLEAR_PREVIOUS_EPOCH_METHOD_AND_CLASS(kls) (TRACE_ID_MASK_CLEAR(kls, PREVIOUS_EPOCH_METHOD_AND_CLASS_BIT_MASK)) #define CLEAR_PREVIOUS_EPOCH_METHOD_FLAG(method) (METHOD_FLAG_CLEAR(method, PREVIOUS_EPOCH_BIT)) #define BLESS_METHOD(method) (METHOD_FLAG_TAG(method, BLESSED_METHOD_BIT)) +#define SET_PRELOAD_TAG_BIT_STICKY(ptr) (TRACE_ID_TAG(ptr, PRELOAD_TAG_BIT_STICKY)) +#define CLEAR_PRELOAD_TAG_BIT_STICKY(ptr) (TRACE_ID_MASK_CLEAR(ptr, PRELOAD_TAG_BIT_STICKY_MASK)) +#define SET_PRELOAD_TAG_BIT_BOOTLOADER(ptr) (TRACE_ID_TAG(ptr, PRELOAD_TAG_BIT_BOOTLOADER)) +#define CLEAR_PRELOAD_TAG_BIT_BOOTLOADER(ptr) (TRACE_ID_MASK_CLEAR(ptr, PRELOAD_TAG_BIT_BOOTLOADER_MASK)) // types #define IS_JDK_JFR_EVENT_KLASS(kls) (TRACE_ID_PREDICATE(kls, JDK_JFR_EVENT_KLASS)) diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index 84c37e91df40..168af9a22e70 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -467,12 +467,15 @@ void JfrRecorderService::safepoint_clear() { _checkpoint_manager.notify_threads(true); JfrDeprecationManager::on_safepoint_clear(); JfrStackTraceRepository::clear(); - // Ensure that non-Java threads cannot perform tagging, enqueuing, - // or event writing that interleaves with the epoch shift. - ConditionalMutexLocker lock(JfrEpochShift_lock, UseShenandoahGC || UseZGC, Mutex::_no_safepoint_check_flag); - _storage.clear(); - _chunkwriter.set_time_stamp(); - _checkpoint_manager.shift_epoch(); + { + // Ensure that non-Java threads cannot perform tagging, enqueuing, + // or event writing that interleaves with the epoch shift. + ConditionalMutexLocker lock(JfrEpochShift_lock, UseShenandoahGC || UseZGC, Mutex::_no_safepoint_check_flag); + _storage.clear(); + _chunkwriter.set_time_stamp(); + _checkpoint_manager.shift_epoch(); + } + JfrStringPool::on_epoch_shift(); } void JfrRecorderService::post_safepoint_clear() { @@ -581,12 +584,15 @@ void JfrRecorderService::safepoint_write() { _checkpoint_manager.on_rotation(); JfrDeprecationManager::on_safepoint_write(); write_stacktrace(_stack_trace_repository, _chunkwriter, true); - // Ensure that non-Java threads cannot perform tagging, enqueuing, - // or event writing that interleaves with the epoch shift. - ConditionalMutexLocker lock(JfrEpochShift_lock, UseShenandoahGC || UseZGC, Mutex::_no_safepoint_check_flag); - _storage.write_at_safepoint(); - _chunkwriter.set_time_stamp(); - _checkpoint_manager.shift_epoch(); + { + // Ensure that non-Java threads cannot perform tagging, enqueuing, + // or event writing that interleaves with the epoch shift. + ConditionalMutexLocker lock(JfrEpochShift_lock, UseShenandoahGC || UseZGC, Mutex::_no_safepoint_check_flag); + _storage.write_at_safepoint(); + _chunkwriter.set_time_stamp(); + _checkpoint_manager.shift_epoch(); + } + JfrStringPool::on_epoch_shift(); } void JfrRecorderService::post_safepoint_write() { diff --git a/src/hotspot/share/jfr/support/jfrClassDefineEvent.cpp b/src/hotspot/share/jfr/support/jfrClassDefineEvent.cpp index e9266ce171ad..acc8661d44fb 100644 --- a/src/hotspot/share/jfr/support/jfrClassDefineEvent.cpp +++ b/src/hotspot/share/jfr/support/jfrClassDefineEvent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,16 @@ #include "classfile/classFileParser.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoaderData.inline.hpp" +#include "classfile/symbolTable.hpp" #include "jfr/instrumentation/jfrClassTransformer.hpp" +#include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/support/jfrClassDefineEvent.hpp" #include "jfr/support/jfrSymbolTable.hpp" #include "jfrfiles/jfrEventClasses.hpp" +#include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/javaThread.hpp" /* @@ -50,8 +54,7 @@ static inline bool is_unnamed_module(const ModuleEntry* module) { return module == nullptr || !module->is_named(); } -static inline bool is_jdk_module(const ModuleEntry* module, JavaThread* jt) { - assert(jt != nullptr, "invariant"); +static inline bool is_jdk_module(const ModuleEntry* module) { if (is_unnamed_module(module)) { return false; } @@ -60,30 +63,81 @@ static inline bool is_jdk_module(const ModuleEntry* module, JavaThread* jt) { return is_jdk_module(module_symbol->as_C_string()); } -static inline bool is_jdk_module(const InstanceKlass* ik, JavaThread* jt) { +static inline bool is_jdk_module(const InstanceKlass* ik) { assert(ik != nullptr, "invariant"); - assert(jt != nullptr, "invariant"); - return is_jdk_module(ik->module(), jt); + return is_jdk_module(ik->module()); } -static traceid module_path(const InstanceKlass* ik, JavaThread* jt) { +static const char* module_source(const InstanceKlass* ik, JavaThread* jt) { assert(ik != nullptr, "invariant"); const ModuleEntry* const module_entry = ik->module(); if (is_unnamed_module(module_entry)) { - return 0; + return nullptr; } const char* const module_name = module_entry->name()->as_C_string(); assert(module_name != nullptr, "invariant"); if (is_jdk_module(module_name)) { const size_t module_name_len = strlen(module_name); - char* const path = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, module_name_len + 6); // "jrt:/" - jio_snprintf(path, module_name_len + 6, "%s%s", "jrt:/", module_name); - return JfrSymbolTable::add(path); + char* const source = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, module_name_len + 6); // "jrt:/" + jio_snprintf(source, module_name_len + 6, "%s%s", "jrt:/", module_name); + return source; + } + return nullptr; +} + +// java_mirror -> ProtectionDomain -> CodeSource + +static const char* allocate(oop string, JavaThread* jt) { + char* str = nullptr; + const typeArrayOop value = java_lang_String::value(string); + if (value != nullptr) { + const size_t length = java_lang_String::utf8_length(string, value); + str = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, length + 1); + java_lang_String::as_utf8_string(string, value, str, length + 1); + } + return str; +} + +static int compute_field_offset(const Klass* klass, const char* field_name, const char* field_signature) { + assert(klass != nullptr, "invariant"); + Symbol* const name = SymbolTable::new_symbol(field_name); + assert(name != nullptr, "invariant"); + Symbol* const signature = SymbolTable::new_symbol(field_signature); + assert(signature != nullptr, "invariant"); + assert(klass->is_instance_klass(), "invariant"); + fieldDescriptor fd; + InstanceKlass::cast(klass)->find_field(name, signature, false, &fd); + return fd.offset(); +} + +static const char* location_no_frag_string(oop codesource, JavaThread* jt) { + assert(codesource != nullptr, "invariant"); + static int loc_no_frag_offset = compute_field_offset(codesource->klass(), "locationNoFragString", "Ljava/lang/String;"); + guarantee(loc_no_frag_offset > 0, "invariant"); + oop string = codesource->obj_field(loc_no_frag_offset); + return string != nullptr ? allocate(string, jt) : nullptr; +} + +static oop code_source(oop pd) { + assert(pd != nullptr, "invariant"); + static int codesource_offset = compute_field_offset(pd->klass(), "codesource", "Ljava/security/CodeSource;"); + return pd->obj_field(codesource_offset); +} + +static const char* code_source(const InstanceKlass* ik, JavaThread* jt) { + assert(ik != nullptr, "invariant"); + assert(ik->java_mirror() != nullptr, "invariant"); + oop pd = java_lang_Class::protection_domain(ik->java_mirror()); + if (pd == nullptr) { + return nullptr; } - return 0; + oop cs = code_source(pd); + return cs != nullptr ? location_no_frag_string(cs, jt) : nullptr; } -static traceid caller_path(const InstanceKlass* ik, JavaThread* jt) { +// Misc source info + +static const char* caller_source(const InstanceKlass* ik, JavaThread* jt) { assert(ik != nullptr, "invariant"); assert(jt != nullptr, "invariant"); assert(ik->class_loader_data()->is_the_null_class_loader_data(), "invariant"); @@ -93,98 +147,107 @@ static traceid caller_path(const InstanceKlass* ik, JavaThread* jt) { const char* caller_name = caller->external_name(); assert(caller_name != nullptr, "invariant"); const size_t caller_name_len = strlen(caller_name); - char* const path = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, caller_name_len + 13); // "instance of " - jio_snprintf(path, caller_name_len + 13, "%s%s", "instance of ", caller_name); - return JfrSymbolTable::add(path); + char* const source = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, caller_name_len + 13); // "instance of " + jio_snprintf(source, caller_name_len + 13, "%s%s", "instance of ", caller_name); + return source; } - return 0; + return nullptr; } -static traceid class_loader_path(const InstanceKlass* ik, JavaThread* jt) { +static const char* class_loader_source(const InstanceKlass* ik, JavaThread* jt) { assert(ik != nullptr, "invariant"); assert(jt != nullptr, "invariant"); assert(!ik->class_loader_data()->is_the_null_class_loader_data(), "invariant"); oop class_loader = ik->class_loader_data()->class_loader(); - const char* class_loader_name = class_loader->klass()->external_name(); - return class_loader_name != nullptr ? JfrSymbolTable::add(class_loader_name) : 0; + return class_loader->klass()->external_name(); } -static inline bool is_not_retransforming(const InstanceKlass* ik, JavaThread* jt) { - return JfrClassTransformer::find_existing_klass(ik, jt) == nullptr; +static const char* misc_source(const InstanceKlass* ik, JavaThread* jt) { + const char* source; + if (is_jdk_module(ik)) { + source = module_source(ik, jt); + } else if (ik->class_loader_data()->is_the_null_class_loader_data()) { + source = caller_source(ik, jt); + } else { + source = class_loader_source(ik, jt); + } + return source; } -static traceid get_source(const InstanceKlass* ik, JavaThread* jt) { - traceid source_id = 0; - if (is_jdk_module(ik, jt)) { - source_id = module_path(ik, jt); - } else if (ik->class_loader_data()->is_the_null_class_loader_data()) { - source_id = caller_path(ik, jt); +/* + * Ordering: + * + * 1. from_boot_loader_modules_image -> module_source + * 2. code source -> the java_mirror->ProtectionDomain->CodeSource->locationNoFragString representation + * 3. misc source -> assorted source constants as a function of state (similar to log output) + */ +static const char* source(const InstanceKlass* ik, bool from_boot_loader_modules_image, JavaThread* jt) { + assert(ik != nullptr, "invariant"); + const char* s = nullptr; + if (from_boot_loader_modules_image) { + assert(is_jdk_module(ik), "invariant"); + s = module_source(ik, jt); } else { - source_id = class_loader_path(ik, jt); + s = code_source(ik, jt); + if (s == nullptr) { + s = misc_source(ik, jt); + } } - return source_id; + return s; } -static inline void send_event(const InstanceKlass* ik, traceid source_id) { - EventClassDefine event; - event.set_definedClass(ik); - event.set_definingClassLoader(ik->class_loader_data()); - event.set_source(source_id); - event.commit(); +static inline bool is_not_retransforming(const InstanceKlass* ik, JavaThread* jt) { + return JfrClassTransformer::find_existing_klass(ik, jt) == nullptr; } void JfrClassDefineEvent::on_creation(const InstanceKlass* ik, const ClassFileParser& parser, JavaThread* jt) { assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invarinat"); assert(ik->trace_id() != 0, "invariant"); assert(!parser.is_internal(), "invariant"); assert(jt != nullptr, "invariant"); - - if (EventClassDefine::is_enabled() && is_not_retransforming(ik, jt)) { - ResourceMark rm(jt); - traceid source_id = 0; - const ClassFileStream& stream = parser.stream(); - if (stream.source() != nullptr) { - if (stream.from_boot_loader_modules_image()) { - assert(is_jdk_module(ik, jt), "invariant"); - source_id = module_path(ik, jt); - } else { - source_id = JfrSymbolTable::add(stream.source()); - } - } else { - source_id = get_source(ik, jt); + if (is_not_retransforming(ik, jt)) { + if (parser.stream().from_boot_loader_modules_image()) { + JfrTraceId::set_preload_bootloader_bit(ik); } - send_event(ik, source_id); } } #if INCLUDE_CDS -static traceid get_source(const AOTClassLocation* cl, JavaThread* jt) { - assert(cl != nullptr, "invariant"); - assert(!cl->is_modules_image(), "invariant"); - const char* const path = cl->path(); - assert(path != nullptr, "invariant"); - size_t len = strlen(path); - const char* file_type = cl->file_type_string(); - assert(file_type != nullptr, "invariant"); - len += strlen(file_type) + 3; // ":/" + null - char* const url = NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, len); - jio_snprintf(url, len, "%s%s%s", file_type, ":/", path); - return JfrSymbolTable::add(url); -} - void JfrClassDefineEvent::on_restoration(const InstanceKlass* ik, JavaThread* jt) { assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invariant"); assert(ik->trace_id() != 0, "invariant"); - assert(jt != nullptr, "invariant"); - - if (EventClassDefine::is_enabled()) { - ResourceMark rm(jt); - assert(is_not_retransforming(ik, jt), "invariant"); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt);) + assert(is_not_retransforming(ik, jt), "invariant"); + if (!ik->defined_by_other_loaders()) { const int index = ik->shared_classpath_index(); assert(index >= 0, "invariant"); const AOTClassLocation* const cl = AOTClassLocationConfig::runtime()->class_location_at(index); assert(cl != nullptr, "invariant"); - send_event(ik, cl->is_modules_image() ? module_path(ik, jt) : get_source(cl, jt)); + if (cl->is_modules_image()) { + JfrTraceId::set_preload_bootloader_bit(ik); + } } } #endif + +static inline void commit_event(const InstanceKlass* ik, const char* s) { + assert(ik != nullptr, "invariant"); + EventClassDefine event; + event.set_definedClass(ik); + event.set_definingClassLoader(ik->class_loader_data()); + event.set_source(s != nullptr ? JfrSymbolTable::add(s) : 0); + event.commit(); +} + +void JfrClassDefineEvent::send_event(const InstanceKlass* ik, bool from_boot_loader_modules_image, JavaThread* jt) { + assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invariant"); + assert(is_not_retransforming(ik, jt), "invariant"); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt);) + if (EventClassDefine::is_enabled()) { + ResourceMark rm(jt); + commit_event(ik, source(ik, from_boot_loader_modules_image, jt)); + } +} diff --git a/src/hotspot/share/jfr/support/jfrClassDefineEvent.hpp b/src/hotspot/share/jfr/support/jfrClassDefineEvent.hpp index 3e242d8e4f2e..496ada13ad30 100644 --- a/src/hotspot/share/jfr/support/jfrClassDefineEvent.hpp +++ b/src/hotspot/share/jfr/support/jfrClassDefineEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ class JavaThread; class JfrClassDefineEvent : AllStatic { public: static void on_creation(const InstanceKlass* ik, const ClassFileParser& parser, JavaThread* jt); + static void send_event(const InstanceKlass* k, bool from_boot_loader_modules_image, JavaThread* jt); CDS_ONLY(static void on_restoration(const InstanceKlass* ik, JavaThread* jt);) }; diff --git a/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp b/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp index bf285c3f41e9..af4ae8a86049 100644 --- a/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp +++ b/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp @@ -73,11 +73,13 @@ void JfrKlassUnloading::clear() { get_unload_set_previous_epoch()->clear(); } -static void add_to_unloaded_klass_set(traceid klass_id) { +void JfrKlassUnloading::add_to_unloaded_set(const Klass* k) { + assert(k != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(USED_ANY_EPOCH(k), "invariant"); JfrCHeapTraceIdSet* const unload_set = get_unload_set(); assert(unload_set != nullptr, "invariant"); - unload_set->add(klass_id); + unload_set->add(JfrTraceId::load_raw(k)); } #if INCLUDE_MANAGEMENT @@ -99,8 +101,11 @@ bool JfrKlassUnloading::on_unload(const Klass* k) { if (IS_JDK_JFR_EVENT_SUBKLASS(k)) { ++event_klass_unloaded_count; } - add_to_unloaded_klass_set(JfrTraceId::load_raw(k)); - return USED_THIS_EPOCH(k) || USED_PREVIOUS_EPOCH(k); + if (USED_ANY_EPOCH(k)) { + add_to_unloaded_set(k); + return true; + } + return false; } static inline bool is_unloaded(const JfrCHeapTraceIdSet* set, const traceid& id) { diff --git a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp index 25ff820fc095..994320cc1119 100644 --- a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp +++ b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ class Klass; class JfrKlassUnloading : AllStatic { public: static bool on_unload(const Klass* k); + static void add_to_unloaded_set(const Klass* k); static int64_t event_class_count(); static bool is_unloaded(traceid klass_id, bool previous_epoch = false); static void clear(); diff --git a/src/hotspot/share/jfr/support/jfrSymbolTable.cpp b/src/hotspot/share/jfr/support/jfrSymbolTable.cpp index c791a05f8181..e9e6a3968f5d 100644 --- a/src/hotspot/share/jfr/support/jfrSymbolTable.cpp +++ b/src/hotspot/share/jfr/support/jfrSymbolTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -340,12 +340,12 @@ inline traceid JfrSymbolTable::Impl::add(const Symbol* sym) { return _symbols->lookup_put(sym->identity_hash(), sym)->id(); } -traceid JfrSymbolTable::Impl::add(const char* str) { +inline traceid JfrSymbolTable::Impl::add(const char* str) { assert(str != nullptr, "invariant"); return _strings->lookup_put(string_hash(str), str)->id(); } -inline traceid JfrSymbolTable::add(const Symbol* sym) { +traceid JfrSymbolTable::add(const Symbol* sym) { return this_epoch_table()->add(sym); } diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.cpp index dc2908e8a811..ced01cfaa48a 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,31 +81,50 @@ int JfrFilterClassClosure::number_of_classes() const { return _classes_to_modify->number_of_entries(); } -void JfrFilterClassClosure::iterate_all_classes(GrowableArray* instrumented_klasses) { +void JfrFilterClassClosure::add(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert(ik != nullptr, "invariant"); + assert(ik->is_loader_alive(), "invariant"); + assert(JfrTraceId::has_sticky_bit(ik), "invariant"); + const traceid klass_id = JfrTraceId::load_raw(ik); + assert(!_classes_to_modify->contains(klass_id), "invariant"); + jclass mirror = mirror_as_local_jni_handle(ik, _thread); + _classes_to_modify->put(klass_id, mirror); +} + +bool JfrFilterClassClosure::do_entry(const traceid& id, const InstanceKlass*& ik) { + if (JfrKlassUnloading::is_unloaded(id, true)) { + // Returning true removes the unloaded entry from the placeholder table. + return true; + } + assert(!ik->is_loaded(), "invariant"); + add(ik); + return false; +} + +void JfrFilterClassClosure::iterate_all_classes(GrowableArray* instrumented_klasses, JfrPlaceholderTable* table) { assert(instrumented_klasses != nullptr, "invariant"); + assert(table != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); // First we process the instrumented_klasses list. The fact that a klass is on that list implies // it matched _some_ previous filter, but we don't know which one. The nice thing is we don't need to know, // because a klass has the STICKY_BIT set for those methods that matched _some_ previous filter. - // We, therefore, put these klasses directly into the classes_to_modify set. We also need to do this - // because some klasses on the instrumented_klasses list may not have reached the point of add_to_hierarchy yet. - // For those klasses, the ClassLoaderDataGraph iterator would not deliver them on iteration. - + // We, therefore, put these klasses directly into the classes_to_modify set. if (instrumented_klasses->is_nonempty()) { for (int i = 0; i < instrumented_klasses->length(); ++i) { if (JfrKlassUnloading::is_unloaded(instrumented_klasses->at(i).trace_id())) { continue; } - const InstanceKlass* const ik = instrumented_klasses->at(i).instance_klass(); - assert(ik != nullptr, "invariant"); - assert(ik->is_loader_alive(), "invariant"); - assert(JfrTraceId::has_sticky_bit(ik), "invariant"); - const traceid klass_id = JfrTraceId::load_raw(ik); - assert(!_classes_to_modify->contains(klass_id), "invariant"); - jclass mirror = mirror_as_local_jni_handle(ik, _thread); - _classes_to_modify->put(klass_id, mirror); + add(instrumented_klasses->at(i).instance_klass()); } } + // We do the same also for the placeholder table because the classes contained + // have not reached the add_to_hierarchy point yet; the ClassLoaderDataGraph iterator + // would not deliver them on iteration. + if (table->number_of_entries() > 0) { + table->unlink(this); + } + ClassLoaderDataGraph::loaded_classes_do_keepalive(this); } diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.hpp index 2febb43ce3ad..593c40be8997 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrClassFilterClosure.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "jni.h" #include "memory/iterator.hpp" +class InstanceKlass; class JavaThread; class JfrFilter; class Klass; @@ -54,6 +55,13 @@ typedef ResizeableHashTable ClosureSet; +typedef ResizeableHashTable JfrPlaceholderTable; + // // Class that collects classes that should be retransformed, // either for adding instrumentation by matching the current @@ -66,14 +74,16 @@ class JfrFilterClassClosure : public KlassClosure { JavaThread* const _thread; bool match(const InstanceKlass* klass) const; + void add(const InstanceKlass* ik); void do_klass(Klass* k); public: JfrFilterClassClosure(JavaThread* thread); - void iterate_all_classes(GrowableArray* instrumented_klasses); + void iterate_all_classes(GrowableArray* instrumented_klasses, JfrPlaceholderTable* table); // Returned set is Resource allocated. ClosureSet* to_modify() const; int number_of_classes() const; + bool do_entry(const traceid& id, const InstanceKlass*& ik); }; #endif // SHARE_JFR_SUPPORT_METHODTRACER_JFRFILTERCLASSCLOSURE_HPP diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp index e094dc973150..90b81c760380 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp @@ -57,6 +57,55 @@ ModuleEntry* JfrMethodTracer::_jdk_jfr_module = nullptr; GrowableArray* JfrMethodTracer::_instrumented_classes = nullptr; GrowableArray* JfrMethodTracer::_timing_entries = nullptr; +constexpr static unsigned int JFR_PLACEHOLDER_TABLE_SIZE = 1009; +constexpr static unsigned int MAX_JFR_PLACEHOLDER_TABLE_SIZE = 0x3fffffff; + +static JfrPlaceholderTable* _placeholder_table = nullptr; // Guarded by ClassLoaderDataGraph_lock + +static JfrPlaceholderTable* placeholder_table() { + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + if (_placeholder_table == nullptr) { + _placeholder_table = new (mtTracing) JfrPlaceholderTable(JFR_PLACEHOLDER_TABLE_SIZE, MAX_JFR_PLACEHOLDER_TABLE_SIZE); + } + return _placeholder_table; +} + +class JfrPlaceholderTableCleaner : StackObj { + public: + bool do_entry(const traceid& id, const InstanceKlass*& ik) { + // Returning true removes the unloaded entry from the placeholder table. + return JfrKlassUnloading::is_unloaded(id, true); + } +}; + +static void clean_unloaded_placeholders() { + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + if (placeholder_table()->number_of_entries() > 0) { + JfrPlaceholderTableCleaner cleaner; + placeholder_table()->unlink(&cleaner); + } +} + +/* + * Since the InstanceKlass* is not yet officially loaded, we need to stage the registration via a placeholder table. + * Iff the InstanceKlass* manages to pass through the class loading pipeline, and become selected for definition, + * we will get a callback to complete the registration process and put it onto the instrumented classes list. + * Only at that point is it safe to enqueue the ik for tagging purposes. + * Since these classes are in the process of loading, they have not yet registered with any JVM support structure + * (e.g., add_to_hierarchy or a dictionary).Therefore, this table is the only means of reaching these classes, + * which is necessary should a new filter be installed. + */ +static void register_placeholder(const InstanceKlass* ik, const JfrMethodProcessor& mp) { + assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invariant"); + assert(!ik->is_scratch_class(), "invariant"); + JfrTraceTagging::tag_preload_sticky(ik); + MutexLocker lock(ClassLoaderDataGraph_lock); + JfrTraceTagging::tag_sticky(ik, mp); + assert(!placeholder_table()->contains(JfrTraceId::load_raw(ik)), "invariant"); + placeholder_table()->put(JfrTraceId::load_raw(ik), ik); +} + // Quick and unlocked check to see if the Method Tracer has been activated. // This is flipped to not null the first time a filter is set and will stay non-null forever. bool JfrMethodTracer::in_use() { @@ -84,7 +133,7 @@ jlongArray JfrMethodTracer::set_filters(JNIEnv* env, jobjectArray classes, jobje JfrFilterClassClosure filter_class_closure(THREAD); { MutexLocker lock(ClassLoaderDataGraph_lock); - filter_class_closure.iterate_all_classes(instrumented_classes()); + filter_class_closure.iterate_all_classes(instrumented_classes(), placeholder_table()); ::clear(instrumented_classes()); } retransform(env, filter_class_closure, THREAD); @@ -128,10 +177,25 @@ void JfrMethodTracer::retransform(JNIEnv* env, const JfrFilterClassClosure& clas } } -static void handle_no_bytecode_result(const InstanceKlass* ik) { +#ifdef ASSERT +static bool in_list(const InstanceKlass* ik, const GrowableArray* list) { + assert(ik != nullptr, "invariant"); + assert(list != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + const JfrInstrumentedClass jic(JfrTraceId::load_raw(ik), ik, false); + return list->find(jic) != -1; +} +#endif + +void JfrMethodTracer::handle_no_bytecode_result(const InstanceKlass* ik) { assert(ik != nullptr, "invariant"); + MutexLocker lock(ClassLoaderDataGraph_lock); if (JfrTraceId::has_sticky_bit(ik)) { - MutexLocker lock(ClassLoaderDataGraph_lock); + if (!ik->is_loaded() && placeholder_table()->remove(JfrTraceId::load_raw(ik))) { + JfrTraceTagging::clear_sticky_for_placeholder(ik); + return; + } + JfrTraceTagging::clear_sticky_methods(ik); JfrTraceTagging::clear_sticky(ik); } } @@ -175,22 +239,28 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par JfrClassTransformer::rewrite_klass_pointer(ik, new_ik, parser, THREAD); // The ik is modified to point to new_ik here. mp.update_methods(existing_ik); existing_ik->module()->add_read(jdk_jfr_module()); + const bool is_loaded = existing_ik->is_loaded(); + MutexLocker lock(ClassLoaderDataGraph_lock); + if (!is_loaded && placeholder_table()->contains(JfrTraceId::load_raw(existing_ik))) { + assert(JfrTraceId::has_sticky_bit(existing_ik), "invariant"); + if (mp.has_timing() && !JfrTraceId::has_timing_bit(existing_ik)) { + JfrTraceId::set_timing_bit(existing_ik); + } + JfrTraceTagging::tag_sticky_for_placeholder_retransform_klass(existing_ik, ik, mp); + return; + } // By setting the sticky bit on the existng klass, we receive a callback into on_klass_redefinition (see below) // when our new methods are installed into the existing klass as part of retransformation / redefinition. // Only when we know our new methods have been installed can we add the klass to the instrumented list (done as part of callback). - JfrTraceTagging::tag_sticky_for_retransform_klass(existing_ik, ik, mp.methods(), mp.has_timing()); + JfrTraceTagging::tag_sticky_for_retransform_klass(existing_ik, ik, mp); return; } // Initial class load. JfrClassTransformer::cache_class_file_data(new_ik, clone, THREAD); // save the initial class file bytes (clone stream) JfrClassTransformer::rewrite_klass_pointer(ik, new_ik, parser, THREAD); // The ik is modified to point to new_ik here. mp.update_methods(ik); - // On initial class load the newly created klass can be installed into the instrumented class list directly. - add_instrumented_class(ik, mp.methods()); - if (mp.has_timing()) { - // After having installed the newly created klass into the list, perform an upcall to publish the associated TimedClass. - JfrUpcalls::publish_method_timers_for_klass(JfrTraceId::load_raw(ik), THREAD); - } + ik->module()->add_read(jdk_jfr_module()); + register_placeholder(ik, mp); } static inline void log_add(const InstanceKlass* ik) { @@ -235,31 +305,55 @@ void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, bool has_ti } } -#ifdef ASSERT -static bool in_instrumented_list(const InstanceKlass* ik, const GrowableArray* list) { - assert(ik != nullptr, "invariant"); - assert(list != nullptr, "invariant"); - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - const JfrInstrumentedClass jic(JfrTraceId::load_raw(ik), ik, false); - return list->find(jic) != -1; +static void remove_from_placeholder_table(traceid id) { + assert(placeholder_table()->contains(id), "invariant"); + placeholder_table()->remove(id); + assert(!placeholder_table()->contains(id), "invariant"); } -#endif -void JfrMethodTracer::add_instrumented_class(InstanceKlass* ik, GrowableArray* methods) { +void JfrMethodTracer::add_instrumented_class(const InstanceKlass* ik, JavaThread* jt) { assert(ik != nullptr, "invariant"); - assert(!ik->is_scratch_class(), "invariant"); - assert(methods->is_nonempty(), "invariant"); - ik->module()->add_read(jdk_jfr_module()); - MutexLocker lock(ClassLoaderDataGraph_lock); - assert(!in_instrumented_list(ik, instrumented_classes()), "invariant"); - JfrTraceTagging::tag_sticky(ik, methods); - const JfrInstrumentedClass jik(JfrTraceId::load_raw(ik), ik, false); - const int idx = instrumented_classes()->append(jik); - if (idx == 0) { - JfrTraceIdEpoch::set_method_tracer_tag_state(); + assert(!ik->is_loaded(), "invariant"); + assert(jt != nullptr, "invariant"); + const traceid id = JfrTraceId::load_raw(ik); + bool has_timing = false; + { + MutexLocker lock(ClassLoaderDataGraph_lock); + if (!JfrTraceId::has_sticky_bit(ik)) { + // A filter retransform removed the sticky bit from the ik + // and the corresponding entry in the placeholder table. + assert(!JfrTraceId::has_timing_bit(ik), "invariant"); + assert(!placeholder_table()->contains(id), "invariant"); + return; + } + remove_from_placeholder_table(id); + has_timing = JfrTraceId::has_timing_bit(ik); + if (has_timing) { + JfrTraceId::clear_timing_bit(ik); + } + JfrTraceTagging::enqueue(ik); + assert(!in_list(ik, instrumented_classes()), "invariant"); + const JfrInstrumentedClass jic(id, ik, false); + const int idx = instrumented_classes()->append(jic); + if (idx == 0) { + JfrTraceIdEpoch::set_method_tracer_tag_state(); + } + assert(in_list(ik, instrumented_classes()), "invariant"); } - assert(in_instrumented_list(ik, instrumented_classes()), "invariant"); log_add(ik); + if (has_timing) { + JfrUpcalls::publish_method_timers_for_klass(id, jt); + } +} + +void JfrMethodTracer::on_definition(const InstanceKlass* ik, JavaThread* jt) { + assert(ik != nullptr, "invariant"); + assert(JfrTraceId::has_preload_sticky_bit(ik), "invariant"); + assert(in_use(), "invariant"); + JfrTraceId::clear_preload_sticky_bit(ik); + // Last station before the ik is enqueued. The lifespan of preload bits ends here. + assert(0 == JfrTraceId::preload_bits(ik), "invariant"); + add_instrumented_class(ik, jt); } ModuleEntry* JfrMethodTracer::jdk_jfr_module() { @@ -338,8 +432,10 @@ void JfrMethodTracer::add_to_unloaded_set(const Klass* k) { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); assert(JfrTraceId::has_sticky_bit(k), "invariant"); assert(_current_unloaded_class_ids != nullptr, "invariant"); - assert(_current_unloaded_class_ids->find(JfrTraceId::load_raw(k)) == -1, "invariant"); - _current_unloaded_class_ids->append(static_cast(JfrTraceId::load_raw(k))); + const jlong id = static_cast(JfrTraceId::load_raw(k)); + if (_current_unloaded_class_ids->find(id) == -1) { + _current_unloaded_class_ids->append(id); + } } // Invoked from JfrTypeSet after having finalized rotation. @@ -360,6 +456,8 @@ void JfrMethodTracer::trim_instrumented_classes(bool trim) { _instrumented_classes = trimmed_classes; } + clean_unloaded_placeholders(); + if (instrumented_classes()->is_nonempty()) { if (!JfrTraceIdEpoch::has_method_tracer_changed_tag_state()) { // Turn the tag state back on for next chunk. diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp index 8a214ab675b4..a106185304f0 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp @@ -53,7 +53,8 @@ class JfrMethodTracer: AllStatic { static ModuleEntry* jdk_jfr_module(); static void add_timing_entry(traceid klass_id); static void retransform(JNIEnv* env, const JfrFilterClassClosure& classes, TRAPS); - static void add_instrumented_class(InstanceKlass* ik, GrowableArray* methods); + static void add_instrumented_class(const InstanceKlass* ik, JavaThread* jt); + static void handle_no_bytecode_result(const InstanceKlass* ik); public: static bool in_use(); @@ -61,6 +62,7 @@ class JfrMethodTracer: AllStatic { static void add_to_unloaded_set(const Klass* k); static void trim_instrumented_classes(bool trim); static GrowableArray* instrumented_classes(); + static void on_definition(const InstanceKlass* ik, JavaThread* jt); static void on_klass_redefinition(const InstanceKlass* ik, bool has_timing); static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS); static jlongArray set_filters(JNIEnv* env, diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp index dc70e70360f2..3e64a3a9d80f 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/support/methodtracer/jfrInstrumentedClass.hpp" +#include "jfr/support/methodtracer/jfrMethodProcessor.hpp" #include "jfr/support/methodtracer/jfrMethodTracer.hpp" +#include "jfr/support/methodtracer/jfrTracedMethod.hpp" #include "jfr/support/methodtracer/jfrTraceTagging.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" @@ -41,6 +43,7 @@ void JfrTraceTagging::tag_dynamic(const Method* method) { } void JfrTraceTagging::tag_sticky(const InstanceKlass* ik) { + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); JfrTraceId::set_sticky_bit(ik); } @@ -53,9 +56,16 @@ void JfrTraceTagging::tag_sticky(const Method* method) { JfrTraceId::set_sticky_bit(method); } -void JfrTraceTagging::tag_sticky(const GrowableArray* methods) { - assert(methods != nullptr, "invariant"); +void JfrTraceTagging::enqueue(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(JfrTraceId::has_sticky_bit(ik), "invariant"); + JfrTraceIdLoadBarrier::enqueue(ik); +} + +void JfrTraceTagging::tag_sticky(const JfrMethodProcessor& mp) { + const GrowableArray* methods = mp.methods(); + assert(methods != nullptr, "invariant"); for (int i = 0; i < methods->length(); ++i) { const Method* const method = methods->at(i).method(); assert(method != nullptr, "invariant"); @@ -63,19 +73,48 @@ void JfrTraceTagging::tag_sticky(const GrowableArray* methods) } } -void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const GrowableArray* methods) { +void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const JfrMethodProcessor& mp) { assert(ik != nullptr, "invariant"); assert(!ik->is_scratch_class(), "invariant"); - assert(methods != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - tag_sticky(methods); - tag_sticky_enqueue(ik); + tag_sticky(mp); + if (mp.has_timing()) { + JfrTraceId::set_timing_bit(ik); + } + tag_sticky(ik); } -void JfrTraceTagging::clear_sticky(const InstanceKlass* ik, bool dynamic_tag /* true */) { +void JfrTraceTagging::tag_preload_sticky(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invariant"); + JfrTraceId::set_preload_sticky_bit(ik); +} + +void JfrTraceTagging::clear_sticky_for_placeholder(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + assert(!ik->is_loaded(), "invariant"); + assert(JfrTraceId::has_sticky_bit(ik), "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + if (JfrTraceId::has_timing_bit(ik)) { + JfrTraceId::clear_timing_bit(ik); + } + const Array* const methods = ik->methods(); + assert(methods != nullptr, "invariant"); + const int length = methods->length(); + for (int i = 0; i < length; ++i) { + const Method* const m = methods->at(i); + if (JfrTraceId::has_sticky_bit(m)) { + JfrTraceId::clear_sticky_bit(m); + } + } + JfrTraceId::clear_sticky_bit(ik); +} + +void JfrTraceTagging::clear_sticky_methods(const InstanceKlass* ik, bool dynamic_tag /* true */) { assert(ik != nullptr, "invariant"); assert(!ik->is_scratch_class(), "invariant"); assert(JfrTraceId::has_sticky_bit(ik), "invariant"); + assert(!ik->is_loaded() || dynamic_tag, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); const Array* const methods = ik->methods(); @@ -90,28 +129,49 @@ void JfrTraceTagging::clear_sticky(const InstanceKlass* ik, bool dynamic_tag /* JfrTraceId::clear_sticky_bit(m); } } +} + +void JfrTraceTagging::clear_sticky(const InstanceKlass* ik, bool dynamic_tag /* true */) { + assert(ik != nullptr, "invariant"); + assert(!ik->is_scratch_class(), "invariant"); + assert(JfrTraceId::has_sticky_bit(ik), "invariant"); + assert(!ik->is_loaded() || dynamic_tag, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); if (dynamic_tag) { tag_dynamic(ik); } JfrTraceId::clear_sticky_bit(ik); } -void JfrTraceTagging::tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray* methods, bool timing) { +void JfrTraceTagging::tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const JfrMethodProcessor& mp) { assert(existing_klass != nullptr, "invariant"); + assert(existing_klass->is_loaded(), "invariant"); assert(scratch_klass != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); // The scratch class has not yet received its official status. // assert(scratch_klass->is_scratch_class(), "invariant"); - if (timing) { - // Can be done outside lock because it is a scratch klass. - // Visibility guaranteed by upcoming safepoint. + if (mp.has_timing()) { JfrTraceId::set_timing_bit(scratch_klass); } - MutexLocker lock(ClassLoaderDataGraph_lock); if (JfrTraceId::has_sticky_bit(existing_klass)) { - clear_sticky(existing_klass); + clear_sticky_methods(existing_klass); + tag_sticky(mp); + enqueue(existing_klass); + return; } - tag_sticky(methods); - tag_sticky(existing_klass); + tag_sticky(mp); + tag_sticky_enqueue(existing_klass); +} + +void JfrTraceTagging::tag_sticky_for_placeholder_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const JfrMethodProcessor& mp) { + assert(existing_klass != nullptr, "invariant"); + assert(!existing_klass->is_loaded(), "invariant"); + assert(scratch_klass != nullptr, "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(JfrTraceId::has_sticky_bit(existing_klass), "invariant"); + // No dynamic tag or enqueuing because the existing class has not been loaded yet. + clear_sticky_methods(existing_klass, false); + tag_sticky(mp); } void JfrTraceTagging::on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass) { @@ -121,11 +181,6 @@ void JfrTraceTagging::on_klass_redefinition(const InstanceKlass* ik, const Insta assert(scratch_klass->is_scratch_class(), "invariant"); assert(SafepointSynchronize::is_at_safepoint(), "invariant"); - const bool klass_has_sticky_bit = JfrTraceId::has_sticky_bit(ik); - if (klass_has_sticky_bit) { - JfrTraceIdLoadBarrier::enqueue(ik); - } - const Array* new_methods = ik->methods(); assert(new_methods != nullptr, "invariant"); @@ -164,8 +219,9 @@ void JfrTraceTagging::on_klass_redefinition(const InstanceKlass* ik, const Insta // A retransformed/redefined klass carrying the sticky bit // needs additional processing by the JfrMethodTracer subsystem. - if (klass_has_sticky_bit) { + if (JfrTraceId::has_sticky_bit(ik)) { assert(JfrMethodTracer::in_use(), "invariant"); + enqueue(ik); JfrMethodTracer::on_klass_redefinition(ik, JfrTraceId::has_timing_bit(scratch_klass)); } } diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp index 38ead4d0fed4..293f9cf1ed91 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,13 @@ #ifndef SHARE_JFR_SUPPORT_METHODTRACER_JFRTRACETAGGING_HPP #define SHARE_JFR_SUPPORT_METHODTRACER_JFRTRACETAGGING_HPP -#include "jfr/support/methodtracer/jfrTracedMethod.hpp" #include "memory/allStatic.hpp" class InstanceKlass; +class JavaThread; +class JfrMethodProcessor; class Method; -template class GrowableArray; - // // Class responsible for setting setting sticky, epoch, and timing bits. // @@ -42,13 +41,18 @@ class JfrTraceTagging : AllStatic { static void tag_dynamic(const Method* method); static void tag_sticky(const InstanceKlass* ik); static void tag_sticky(const Method* method); - static void tag_sticky(const GrowableArray* methods); + static void tag_sticky(const JfrMethodProcessor& mp); static void tag_sticky_enqueue(const InstanceKlass* ik); public: static void clear_sticky(const InstanceKlass* ik, bool dynamic_tag = true); - static void tag_sticky(const InstanceKlass* ik, const GrowableArray* methods); - static void tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray* methods, bool timing); + static void clear_sticky_methods(const InstanceKlass* ik, bool dynamic_tag = true); + static void clear_sticky_for_placeholder(const InstanceKlass* ik); + static void tag_sticky(const InstanceKlass* ik, const JfrMethodProcessor& mp); + static void tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const JfrMethodProcessor& mp); + static void tag_sticky_for_placeholder_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const JfrMethodProcessor& mp); static void on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass); + static void enqueue(const InstanceKlass* ik); + static void tag_preload_sticky(const InstanceKlass* ik); }; #endif /* SHARE_JFR_SUPPORT_METHODTRACER_JFRTRACETAGGING_HPP */ diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index 4b8bcb8e0ef0..5edc9813c9bd 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -376,7 +376,6 @@ Method* ConstantPoolCache::method_if_resolved(int method_index) const { } ConstantPoolCache* ConstantPoolCache::allocate(ClassLoaderData* loader_data, - const intStack& invokedynamic_map, const GrowableArray indy_entries, const GrowableArray field_entries, const GrowableArray method_entries, @@ -390,7 +389,7 @@ ConstantPoolCache* ConstantPoolCache::allocate(ClassLoaderData* loader_data, Array* resolved_method_entries = initialize_resolved_entries_array(loader_data, method_entries, CHECK_NULL); return new (loader_data, size, MetaspaceObj::ConstantPoolCacheType, THREAD) - ConstantPoolCache(invokedynamic_map, resolved_indy_entries, resolved_field_entries, resolved_method_entries); + ConstantPoolCache(resolved_indy_entries, resolved_field_entries, resolved_method_entries); } // Record the GC marking cycle when redefined vs. when found in the loom stack chunks. diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp index 1a331e703b4d..7f4532f99143 100644 --- a/src/hotspot/share/oops/cpCache.hpp +++ b/src/hotspot/share/oops/cpCache.hpp @@ -91,16 +91,12 @@ class ConstantPoolCache: public MetaspaceObj { }; // Constructor - ConstantPoolCache(const intStack& invokedynamic_references_map, - Array* indy_info, + ConstantPoolCache(Array* indy_info, Array* field_entries, Array* mehtod_entries); - // Initialization - void initialize(const intArray& invokedynamic_references_map); public: static ConstantPoolCache* allocate(ClassLoaderData* loader_data, - const intStack& invokedynamic_references_map, const GrowableArray indy_entries, const GrowableArray field_entries, const GrowableArray method_entries, diff --git a/src/hotspot/share/oops/cpCache.inline.hpp b/src/hotspot/share/oops/cpCache.inline.hpp index fad5931ba180..9d8fbc5be1c6 100644 --- a/src/hotspot/share/oops/cpCache.inline.hpp +++ b/src/hotspot/share/oops/cpCache.inline.hpp @@ -35,8 +35,7 @@ #include "runtime/atomicAccess.hpp" // Constructor -inline ConstantPoolCache::ConstantPoolCache(const intStack& invokedynamic_references_map, - Array* invokedynamic_info, +inline ConstantPoolCache::ConstantPoolCache(Array* invokedynamic_info, Array* field_entries, Array* method_entries) : _constant_pool(nullptr), diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index d13ae7117f39..b99fff3da28f 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -841,6 +841,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec assert(is_klass(), "ensure C++ vtable is restored"); assert(in_aot_cache(), "must be set"); assert(secondary_supers()->length() >= (int)population_count(_secondary_supers_bitmap), "must be"); + JFR_ONLY(Jfr::on_restoration(this, THREAD);) if (log_is_enabled(Trace, aot, unshareable)) { ResourceMark rm(THREAD); oop class_loader = loader_data->class_loader(); @@ -859,8 +860,6 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec // (same order as class file parsing) loader_data->add_class(this); - JFR_ONLY(Jfr::on_restoration(this, THREAD);) - Handle loader(THREAD, loader_data->class_loader()); ModuleEntry* module_entry = nullptr; Klass* k = this; diff --git a/src/hotspot/share/oops/markWord.cpp b/src/hotspot/share/oops/markWord.cpp index 2201633b160a..3ce3f5dc7405 100644 --- a/src/hotspot/share/oops/markWord.cpp +++ b/src/hotspot/share/oops/markWord.cpp @@ -23,9 +23,6 @@ */ #include "oops/markWord.hpp" -#include "runtime/basicLock.inline.hpp" -#include "runtime/javaThread.hpp" -#include "runtime/objectMonitor.inline.hpp" #include "utilities/ostream.hpp" #ifdef _LP64 @@ -34,60 +31,39 @@ STATIC_ASSERT(markWord::klass_shift + markWord::klass_bits == 64); STATIC_ASSERT(markWord::klass_shift == markWord::hash_bits + markWord::hash_shift); #endif -markWord markWord::displaced_mark_helper() const { - assert(has_displaced_mark_helper(), "check"); - // Make sure we have an inflated monitor. - guarantee(has_monitor(), "bad header=" INTPTR_FORMAT, value()); - ObjectMonitor* monitor = this->monitor(); - return monitor->header(); -} - -void markWord::set_displaced_mark_helper(markWord m) const { - assert(has_displaced_mark_helper(), "check"); - // Make sure we have an inflated monitor. - guarantee(has_monitor(), "bad header=" INTPTR_FORMAT, value()); - ObjectMonitor* monitor = this->monitor(); - monitor->set_header(m); -} - -void markWord::print_on(outputStream* st, bool print_monitor_info) const { - if (is_marked()) { // last bits = 11 +void markWord::print_on(outputStream* st) const { + if (is_marked()) { // last bits = 11 st->print(" marked(" INTPTR_FORMAT ")", value()); - } else if (has_monitor()) { // last bits = 10 - // have to check has_monitor() before is_locked() - // Valhalla: inline types/arrays can't be monitored - st->print(" monitor(" INTPTR_FORMAT ")=", value()); - } else if (is_locked()) { // last bits != 01 => 00 - // thin locked - // Valhalla: inline types can not possess an object monitor - st->print(" locked(" INTPTR_FORMAT ")", value()); + return; + } + st->print(" mark("); + if (has_monitor()) { // last bits = 10 + st->print("has_monitor"); + } else if (is_lock_neutral()) { // last bits = 01 + st->print("is_lock_neutral"); + } else { // last bits = 00 + assert(is_fast_locked(), "should be"); + st->print("is_fast_locked"); + } + if (is_inline_type()) { + st->print(" inline_type"); + } + if (has_hash()) { + st->print(" hash=" INTPTR_FORMAT, hash()); } else { - st->print(" mark("); - if (is_unlocked()) { // last bits = 01 - st->print("is_unlocked"); - if (is_inline_type()) { - st->print(" inline_type"); - } - if (has_no_hash()) { - st->print(" no_hash"); - } else { - st->print(" hash=" INTPTR_FORMAT, hash()); - } + st->print(" no_hash"); + } #ifdef _LP64 // 64 bit encodings have array information - // flat or null-free do not imply each other - bool flat = is_flat_array(); - bool null_free = is_null_free_array(); - if (flat && !null_free) { - st->print(" flat_array"); - } else if (!flat && null_free) { - st->print(" null_free_array"); - } else if (flat && null_free) { - st->print(" flat_null_free_array"); - } -#endif - } else { - st->print("??"); - } - st->print(" age=%d)", age()); + // flat or null-free do not imply each other + const bool flat = is_flat_array(); + const bool null_free = is_null_free_array(); + if (flat && !null_free) { + st->print(" flat_array"); + } else if (!flat && null_free) { + st->print(" null_free_array"); + } else if (flat && null_free) { + st->print(" flat_null_free_array"); } +#endif + st->print(" age=%d)", age()); } diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index 42ced7df0b2d..7cb1e5b57285 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -49,13 +49,13 @@ // ------------------------------- // klass:22 hash:31 valhalla:4 age:4 self-fwd:1 lock:2 // -// - lock bits are used to describe lock states: locked/unlocked/monitor-locked +// - lock bits are used to describe lock states: fast-locked/lock-neutral/inflated // and to indicate that an object has been GC marked / forwarded. // -// [header | 00] locked locked regular object header (fast-locking in use) -// [header | 01] unlocked regular object header -// [header | 10] monitor inflated lock -// [ptr | 11] marked used to mark an object (header is swapped out) +// [header | 00] fast_locked object has been fast-locked +// [header | 01] lock_neutral object has no monitor and is not locked +// [header | 10] monitor object has a monitor (lock state recorded there) +// [ptr | 11] marked used to mark an object (header is swapped out) // // - self-fwd - used by some GCs to indicate in-place forwarding. // @@ -73,16 +73,18 @@ // * null-free arrays: An array instance without null elements // * valhalla reserved: Reserved for future use // -// Inline types cannot be locked and do not have an identity hash. +// Inline types cannot be locked. // -// - hash - contains the identity hash value: largest value is 31 bits, see +// Inline types have a deterministic hash based on the immutable payload +// and class, which may be cached in the markWord. +// +// - hash - contains the hash value: largest value is 31 bits, see // os::random(). Also, 64-bit VMs require a hash value no bigger than 32 // bits because they will not properly generate a mask larger than that: // see library_call.cpp // // - klass - klass identifier used when UseCompactObjectHeaders == true -class ObjectMonitor; class outputStream; class markWord { @@ -177,17 +179,17 @@ class markWord { static constexpr uintptr_t klass_mask_in_place = klass_mask << klass_shift; #endif - static const uintptr_t locked_value = 0; - static const uintptr_t unlocked_value = 1; + static const uintptr_t fast_locked_value = 0; + static const uintptr_t lock_neutral_value = 1; static const uintptr_t monitor_value = 2; static const uintptr_t marked_value = 3; - static const uintptr_t inline_type_pattern = inline_type_bit_in_place | unlocked_value; - static const uintptr_t inline_type_pattern_mask = inline_type_bit_in_place | lock_mask_in_place; + static const uintptr_t inline_type_pattern = inline_type_bit_in_place; + static const uintptr_t inline_type_pattern_mask = inline_type_bit_in_place; static const uintptr_t no_hash = 0 ; // no hash value assigned static const uintptr_t no_hash_in_place = (uintptr_t)no_hash << hash_shift; - static const uintptr_t no_lock_in_place = unlocked_value; + static const uintptr_t no_lock_in_place = lock_neutral_value; static const uint max_age = age_mask; @@ -195,6 +197,7 @@ class markWord { static markWord zero() { return markWord(uintptr_t(0)); } bool is_inline_type() const { + precond(!is_marked()); #ifdef _LP64 // 64 bit encodings only return (mask_bits(value(), inline_type_pattern_mask) == inline_type_pattern); #else @@ -203,22 +206,16 @@ class markWord { } // lock accessors (note that these assume lock_shift == 0) - bool is_locked() const { - return (mask_bits(value(), lock_mask_in_place) != unlocked_value); - } - bool is_unlocked() const { - return (mask_bits(value(), lock_mask_in_place) == unlocked_value); + STATIC_ASSERT(lock_shift == 0); + + bool is_lock_neutral() const { + return (mask_bits(value(), lock_mask_in_place) == lock_neutral_value); } + bool is_marked() const { return (mask_bits(value(), lock_mask_in_place) == marked_value); } - bool is_neutral() const { // Not locked, or marked - a "clean" neutral state - LP64_ONLY(assert(!is_unlocked() || mask_bits(value(), inline_type_bit_in_place) == 0, - "Inline types should not be used for locking. _value: " PTR_FORMAT, _value)); - return (mask_bits(value(), lock_mask_in_place) == unlocked_value); - } - bool is_forwarded() const { // Returns true for normal forwarded (0b011) and self-forwarded (0b1xx). return mask_bits(value(), lock_mask_in_place | self_fwd_bit_in_place) >= static_cast(marked_value); @@ -226,24 +223,24 @@ class markWord { // Should this header be preserved during GC? bool must_be_preserved() const { - // The reserved bits are only guaranteed to be unset if the mark word is "unlocked" - LP64_ONLY(assert(!is_unlocked() || mask_bits(value(), valhalla_reserved_bit_in_place) == 0, + precond(!is_marked()); + LP64_ONLY(assert(mask_bits(value(), valhalla_reserved_bit_in_place) == 0, "Reserved bits should not be used. _value: " PTR_FORMAT, _value)); - return !is_unlocked() || !has_no_hash(); + return !is_lock_neutral() || has_hash(); } // WARNING: The following routines are used EXCLUSIVELY by // synchronization functions. They are not really gc safe. // They must get updated if markWord layout get changed. - markWord set_unlocked() const { - return markWord(value() | unlocked_value); + markWord set_lock_neutral() const { + return markWord((value() & ~lock_mask_in_place) | lock_neutral_value); } bool is_fast_locked() const { - return (value() & lock_mask_in_place) == locked_value; + return (value() & lock_mask_in_place) == fast_locked_value; } markWord set_fast_locked() const { - // Clear the lock_mask_in_place bits to set locked_value: + // Clear the lock_mask_in_place bits to set fast_locked_value: return markWord(value() & ~lock_mask_in_place); } @@ -253,35 +250,14 @@ class markWord { markWord set_has_monitor() const { return markWord((value() & ~lock_mask_in_place) | monitor_value); } - ObjectMonitor* monitor() const { - // Locking with OM table does not use markWord for monitors. - ShouldNotCallThis(); - return (ObjectMonitor*) nullptr; - } - - static markWord encode(ObjectMonitor* monitor) { - // Locking with OM table does not use markWord for monitors. - ShouldNotCallThis(); - return markWord(0); - } - - bool has_monitor_pointer() const { - return false; // Locking with OM table does not use markWord for monitors. - } - - bool has_displaced_mark_helper() const { - return has_monitor_pointer(); - } - markWord displaced_mark_helper() const; - void set_displaced_mark_helper(markWord m) const; // used to encode pointers during GC markWord clear_lock_bits() const { return markWord(value() & ~lock_mask_in_place); } - // age operations markWord set_marked() { return markWord((value() & ~lock_mask_in_place) | marked_value); } - markWord set_unmarked() { return markWord((value() & ~lock_mask_in_place) | unlocked_value); } + markWord set_unmarked() { return markWord((value() & ~lock_mask_in_place) | lock_neutral_value); } + // age operations uint age() const { return (uint) mask_bits(value() >> age_shift, age_mask); } markWord set_age(uint v) const { assert((v & ~age_mask) == 0, "shouldn't overflow age field"); @@ -291,15 +267,16 @@ class markWord { // hash operations intptr_t hash() const { + precond(!is_marked()); return mask_bits(value() >> hash_shift, hash_mask); } - bool has_no_hash() const { - return hash() == no_hash; + bool has_hash() const { + precond(!is_marked()); + return hash() != no_hash; } bool is_flat_array() const { - assert(!has_monitor_pointer(), "Bits are not valid if replaced by a monitor pointer: " PTR_FORMAT, value()); assert(!is_marked(), "Bits might not be valid if marked by the GC: " PTR_FORMAT, value()); #ifdef _LP64 // 64 bit encodings only return (mask_bits(value(), flat_array_bit_in_place) != 0); @@ -309,7 +286,6 @@ class markWord { } bool is_null_free_array() const { - assert(!has_monitor_pointer(), "Bits are not valid if replaced by a monitor pointer: " PTR_FORMAT, value()); assert(!is_marked(), "Bits might not be valid if marked by the GC: " PTR_FORMAT, value()); #ifdef _LP64 // 64 bit encodings only return (mask_bits(value(), null_free_array_bit_in_place) != 0); @@ -333,30 +309,30 @@ class markWord { // Prototype marks for initialization static markWord prototype() { - return markWord(unlocked_value); + return markWord(lock_neutral_value); } static markWord inline_type_prototype() { NOT_LP64(assert(false, "Should not be called in 32 bit mode")); - return markWord(unlocked_value | inline_type_bit_in_place); + return markWord(lock_neutral_value | inline_type_bit_in_place); } static markWord flat_array_prototype(bool null_free) { NOT_LP64(assert(false, "Should not be called in 32 bit mode")); if (null_free) { - return markWord(unlocked_value | flat_array_bit_in_place | null_free_array_bit_in_place); + return markWord(lock_neutral_value | flat_array_bit_in_place | null_free_array_bit_in_place); } else { - return markWord(unlocked_value | flat_array_bit_in_place); + return markWord(lock_neutral_value | flat_array_bit_in_place); } } static markWord null_free_array_prototype() { NOT_LP64(assert(false, "Should not be called in 32 bit mode")); - return markWord(unlocked_value | null_free_array_bit_in_place); + return markWord(lock_neutral_value | null_free_array_bit_in_place); } // Debugging - void print_on(outputStream* st, bool print_monitor_info = true) const; + void print_on(outputStream* st) const; // Prepare address of oop for placement into mark inline static markWord encode_pointer_as_mark(void* p) { return from_pointer(p).set_marked(); } diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index f3ff17cd9ca5..6e35f05c9ce5 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1703,6 +1703,14 @@ bool MethodData::profile_parameters_jsr292_only() { return profile_parameters_flag() == type_profile_jsr292; } +bool MethodData::profile_array_accesses() { + return COMPILER2_PRESENT(UseArrayLoadStoreProfile ||) TypeProfileLevel > 0; +} + +bool MethodData::profile_acmp() { + return COMPILER2_PRESENT(UseACmpProfile ||) TypeProfileLevel > 0; +} + bool MethodData::profile_all_parameters() { return profile_parameters_flag() == type_profile_all; } @@ -1914,6 +1922,15 @@ void MethodData::deallocate_contents(ClassLoaderData* loader_data) { release_C_heap_structures(); } +void MethodData::release_C_heap_structures() { + // The class unloading protocol guarantees that this object is + // unreachable at this point, so no synchronization is necessary. + if (_extra_data_lock != nullptr) { + delete _extra_data_lock; + _extra_data_lock = nullptr; + } +} + #if INCLUDE_CDS void MethodData::remove_unshareable_info() { _extra_data_lock = nullptr; diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 19ea9ac3ea11..02072262b16b 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -2701,7 +2701,7 @@ class MethodData : public Metadata { // Deallocation support void deallocate_contents(ClassLoaderData* loader_data); - void release_C_heap_structures() {} + void release_C_heap_structures(); // GC support void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; } @@ -2724,6 +2724,8 @@ class MethodData : public Metadata { static bool profile_arguments_jsr292_only(); static bool profile_return(); static bool profile_parameters(); + static bool profile_array_accesses(); + static bool profile_acmp(); static bool profile_return_jsr292_only(); void clean_method_data(bool always_clean); diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index a9900bf1509c..4a7c7ad688d1 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -115,10 +115,30 @@ void oopDesc::verify(oopDesc* oop_desc) { verify_on(tty, oop_desc); } -intptr_t oopDesc::slow_identity_hash() { - // slow case; we have to acquire the micro lock in order to locate the header - Thread* current = Thread::current(); - return ObjectSynchronizer::FastHashCode(current, this); +intptr_t oopDesc::slow_identity_hash(markWord current_mark, Thread* current) { + precond(!current_mark.has_hash()); + + assert(!is_inline(), "slow_identity_hash should not be called for value objects"); + + // Calculate the new hash + const intptr_t new_hash = ObjectSynchronizer::get_next_hash(current, this); + + markWord mark = current_mark; + while (true) { + const markWord old_mark = mark; + const markWord new_mark = mark.copy_set_hash(new_hash); + + // Try to install the hash + mark = cas_set_mark(new_mark, old_mark, memory_order_relaxed); + if (old_mark == mark) { + // CAS succeded, return the installed hash + return new_hash; + } else if (mark.has_hash()) { + // Another thread installed a hash, return the installed hash + return mark.hash(); + } + // CAS failed, retry + } } // used only for asserts and guarantees diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 831250b81a47..349c5f5a518f 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -261,10 +261,6 @@ class oopDesc { static void verify_on(outputStream* st, oopDesc* oop_desc); static void verify(oopDesc* oopDesc); - // locking operations - inline bool is_locked() const; - inline bool is_unlocked() const; - // asserts and guarantees static bool is_oop(oop obj); static bool is_oop_or_null(oop obj); @@ -316,15 +312,13 @@ class oopDesc { inline static bool is_instanceof_or_null(oop obj, Klass* klass); // identity hash; returns the identity hash key (computes it if necessary) - inline intptr_t identity_hash(); - intptr_t slow_identity_hash(); - inline bool fast_no_hash_check(); + inline intptr_t identity_hash(Thread* current = nullptr); + inline bool has_identity_hash(); - // marks are forwarded to stack when object is locked - inline bool has_displaced_mark() const; - inline markWord displaced_mark() const; - inline void set_displaced_mark(markWord m); +private: + intptr_t slow_identity_hash(markWord current_mark, Thread* current); +public: // Checks if the mark word needs to be preserved inline bool mark_must_be_preserved() const; inline bool mark_must_be_preserved(markWord m) const; diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index fb536b923c40..864fbc5e5e72 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -272,14 +272,6 @@ inline void oopDesc::float_field_put(int offset, jfloat value) { *field_add inline jdouble oopDesc::double_field(int offset) const { return *field_addr(offset); } inline void oopDesc::double_field_put(int offset, jdouble value) { *field_addr(offset) = value; } -bool oopDesc::is_locked() const { - return mark().is_locked(); -} - -bool oopDesc::is_unlocked() const { - return mark().is_unlocked(); -} - bool oopDesc::is_gc_marked() const { return mark().is_marked(); } @@ -339,7 +331,6 @@ oop oopDesc::forwardee(markWord mark) const { } } -// Note that the forwardee is not the same thing as the displaced_mark. // The forwardee is used when copying during scavenge and mark-sweep. // It does need to clear the low two locking- and GC-related bits. oop oopDesc::forwardee() const { @@ -354,21 +345,13 @@ void oopDesc::unset_self_forwarded() { uint oopDesc::age() const { markWord m = mark(); assert(!m.is_marked(), "Attempt to read age from forwarded mark"); - if (m.has_displaced_mark_helper()) { - return m.displaced_mark_helper().age(); - } else { - return m.age(); - } + return m.age(); } void oopDesc::incr_age() { markWord m = mark(); assert(!m.is_marked(), "Attempt to increment age of forwarded mark"); - if (m.has_displaced_mark_helper()) { - m.set_displaced_mark_helper(m.displaced_mark_helper().incr_age()); - } else { - set_mark(m.incr_age()); - } + set_mark(m.incr_age()); } template @@ -413,37 +396,21 @@ bool oopDesc::is_instanceof_or_null(oop obj, Klass* klass) { return obj == nullptr || obj->klass()->is_subtype_of(klass); } -intptr_t oopDesc::identity_hash() { - // Fast case; if the object is unlocked and the hash value is set, no locking is needed +intptr_t oopDesc::identity_hash(Thread* current) { // Note: The mark must be read into local variable to avoid concurrent updates. markWord mrk = mark(); - if (mrk.is_unlocked() && !mrk.has_no_hash()) { - return mrk.hash(); - } else if (mrk.is_marked()) { - return mrk.hash(); - } else { - return slow_identity_hash(); - } -} - -// This checks fast simple case of whether the oop has_no_hash, -// to optimize JVMTI table lookup. -bool oopDesc::fast_no_hash_check() { - markWord mrk = mark_acquire(); assert(!mrk.is_marked(), "should never be marked"); - return mrk.is_unlocked() && mrk.has_no_hash(); -} -bool oopDesc::has_displaced_mark() const { - return mark().has_displaced_mark_helper(); -} + if (mrk.has_hash()) { + return mrk.hash(); + } -markWord oopDesc::displaced_mark() const { - return mark().displaced_mark_helper(); + return slow_identity_hash(mrk, current == nullptr ? Thread::current() : current); } -void oopDesc::set_displaced_mark(markWord m) { - mark().set_displaced_mark_helper(m); +bool oopDesc::has_identity_hash() { + markWord mrk = mark_acquire(); + return mrk.has_hash(); } bool oopDesc::mark_must_be_preserved() const { diff --git a/src/hotspot/share/oops/symbol.hpp b/src/hotspot/share/oops/symbol.hpp index 2fc664dfab2d..1acca970039c 100644 --- a/src/hotspot/share/oops/symbol.hpp +++ b/src/hotspot/share/oops/symbol.hpp @@ -101,7 +101,8 @@ class ClassLoaderData; #define PERM_REFCOUNT 0xffff #endif -class Symbol : public MetaspaceObj { +// VerificationType::TypeMask == 0x7 demands 8-byte aligned Symbol* +class alignas(8) Symbol : public MetaspaceObj { friend class VMStructs; friend class SymbolTable; friend class vmSymbols; diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp index 8c94dd41789d..3bf612bb468f 100644 --- a/src/hotspot/share/opto/arraycopynode.cpp +++ b/src/hotspot/share/opto/arraycopynode.cpp @@ -818,10 +818,6 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr* t_oop, MemBarNode* mb, PhaseVal Node* c = mb->in(0); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - // step over g1 gc barrier if we're at e.g. a clone with ReduceInitialCardMarks off - c = bs->step_over_gc_barrier(c); - CallNode* call = nullptr; guarantee(c != nullptr, "step_over_gc_barrier failed, there must be something to step to."); if (c->is_Region()) { @@ -836,6 +832,7 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr* t_oop, MemBarNode* mb, PhaseVal } } else if (may_modify_helper(t_oop, c->in(0), phase, ac)) { #ifdef ASSERT + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); bool use_ReduceInitialCardMarks = BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && static_cast(bs)->use_ReduceInitialCardMarks(); assert(c == mb->in(0) || (ac->is_clonebasic() && !use_ReduceInitialCardMarks), "only for clone"); diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 33799f25d4f4..76639a5ef817 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -70,6 +70,9 @@ develop(bool, StressBailout, false, \ "Perform bailouts randomly at C2 failing() checks") \ \ + develop(bool, StressVerifyMeetJoin, false, \ + "Perform cross meet/join sanity checks on all Type instances") \ + \ product(bool, OptimizeReachabilityFences, true, DIAGNOSTIC, \ "Optimize reachability fences " \ "(leave reachability fence nodes intact when turned off)") \ @@ -245,6 +248,9 @@ product(bool, UseCountedLoopSafepoints, false, \ "Force counted loops to keep a safepoint") \ \ + product(bool, UseParsePredicates, true, DIAGNOSTIC, \ + "Use Parse Predicates for speculative optimizations.") \ + \ product(bool, UseLoopPredicate, true, \ "Move checks with uncommon trap out of loops.") \ \ @@ -257,6 +263,11 @@ develop(bool, TraceSplitIf, false, \ "Trace Split-If optimization") \ \ + product(bool, UseLoopLimitCheckPredicate, true, DIAGNOSTIC, \ + "Use Loop Limit Check Predicate to speculatively transform " \ + "loops to counted loops where overflow is uncertain at " \ + "compile time.") \ + \ develop(bool, TraceLoopLimitCheck, false, \ "Trace generation of loop limits checks") \ \ diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index d2926f4ebb98..65b5ae1d1de7 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1261,12 +1261,13 @@ bool CallStaticJavaNode::is_uncommon_trap() const { int CallStaticJavaNode::uncommon_trap_request() const { return is_uncommon_trap() ? extract_uncommon_trap_request(this) : 0; } + int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) { #ifndef PRODUCT if (!(call->req() > TypeFunc::Parms && call->in(TypeFunc::Parms) != nullptr && - call->in(TypeFunc::Parms)->is_Con() && - call->in(TypeFunc::Parms)->bottom_type()->isa_int())) { + call->in(TypeFunc::Parms)->bottom_type()->isa_int() && + call->in(TypeFunc::Parms)->bottom_type()->is_int()->is_con())) { assert(in_dump() != 0, "OK if dumping"); tty->print("[bad uncommon trap]"); return 0; @@ -1560,6 +1561,9 @@ Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { assert(IncrementalInlineVirtual, "required"); assert(cg->call_node() == this, "mismatch"); + Node* receiver_node = in(TypeFunc::Parms); + const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); + if (cg->callee_method() == nullptr) { // Recover symbolic info for method resolution. ciMethod* caller = jvms()->method(); @@ -1578,9 +1582,6 @@ Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - Node* receiver_node = in(TypeFunc::Parms); - const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); - int not_used3; bool call_does_dispatch; ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/, @@ -1589,8 +1590,9 @@ Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { cg->set_callee_method(callee); } } - if (cg->callee_method() != nullptr) { - // Register for late inlining. + if (cg->callee_method() != nullptr && receiver_type != nullptr && !receiver_type->maybe_null()) { + // Only register for late inlining if the receiver is null-free because + // LateInlineVirtualCallGenerator::do_late_inline_check() rejects nullable receivers. register_for_late_inline(); // MH late inlining prepends to the list, so do the same } } else { @@ -2360,9 +2362,8 @@ bool AbstractLockNode::find_matching_unlock(const Node* ctrl, LockNode* lock, Node *n = ctrl_proj->in(0); if (n != nullptr && n->is_Unlock()) { UnlockNode *unlock = n->as_Unlock(); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node()); - Node* unlock_obj = bs->step_over_gc_barrier(unlock->obj_node()); + Node* lock_obj = lock->obj_node(); + Node* unlock_obj = unlock->obj_node(); if (lock_obj->eqv_uncast(unlock_obj) && BoxLockNode::same_slot(lock->box_node(), unlock->box_node()) && !unlock->is_eliminated()) { @@ -2408,9 +2409,8 @@ LockNode *AbstractLockNode::find_matching_lock(UnlockNode* unlock) { } if (ctrl->is_Lock()) { LockNode *lock = ctrl->as_Lock(); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node()); - Node* unlock_obj = bs->step_over_gc_barrier(unlock->obj_node()); + Node* lock_obj = lock->obj_node(); + Node* unlock_obj = unlock->obj_node(); if (lock_obj->eqv_uncast(unlock_obj) && BoxLockNode::same_slot(lock->box_node(), unlock->box_node())) { lock_result = lock; @@ -2442,9 +2442,8 @@ bool AbstractLockNode::find_lock_and_unlock_through_if(Node* node, LockNode* loc } if (lock1_node != nullptr && lock1_node->is_Lock()) { LockNode *lock1 = lock1_node->as_Lock(); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node()); - Node* lock1_obj = bs->step_over_gc_barrier(lock1->obj_node()); + Node* lock_obj = lock->obj_node(); + Node* lock1_obj = lock1->obj_node(); if (lock_obj->eqv_uncast(lock1_obj) && BoxLockNode::same_slot(lock->box_node(), lock1->box_node()) && !lock1->is_eliminated()) { @@ -2705,8 +2704,6 @@ bool LockNode::is_nested_lock_region(Compile * c) { return false; } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - obj = bs->step_over_gc_barrier(obj); // Look for external lock for the same object. SafePointNode* sfn = this->as_SafePoint(); JVMState* youngest_jvms = sfn->jvms(); @@ -2717,7 +2714,6 @@ bool LockNode::is_nested_lock_region(Compile * c) { // Loop over monitors for (int idx = 0; idx < num_mon; idx++) { Node* obj_node = sfn->monitor_obj(jvms, idx); - obj_node = bs->step_over_gc_barrier(obj_node); BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock(); if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) { box->set_nested(); diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index fbecaba01a50..8d8e4111f922 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -50,6 +50,7 @@ #include "memory/resourceArea.hpp" #include "opto/addnode.hpp" #include "opto/block.hpp" +#include "opto/c2_globals.hpp" #include "opto/c2compiler.hpp" #include "opto/callGenerator.hpp" #include "opto/callnode.hpp" @@ -435,8 +436,6 @@ void Compile::remove_useless_node(Node* dead) { remove_unstable_if_trap(dead->as_CallStaticJava(), false); } } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bs->unregister_potential_barrier_node(dead); } // Disconnect all useless nodes by disconnecting those at the boundary. @@ -497,8 +496,6 @@ void Compile::disconnect_useless_nodes(Unique_Node_List& useful, Unique_Node_Lis } #endif - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bs->eliminate_useless_gc_barriers(useful, this); // clean up the late inline lists remove_useless_late_inlines( &_late_inlines, useful); remove_useless_late_inlines( &_string_late_inlines, useful); @@ -944,6 +941,12 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, // Now generate code Code_Gen(); + +#ifdef ASSERT + if (StressVerifyMeetJoin) { + Type::verify_meet_join(); + } +#endif // ASSERT } // C2 uses runtime stubs serialized generation to initialize its static tables @@ -3089,7 +3092,7 @@ void Compile::Optimize() { } assert(!has_vbox_nodes(), "sanity"); - if (!failing() && RenumberLiveNodes && live_nodes() + NodeLimitFudgeFactor < unique()) { + if (RenumberLiveNodes && live_nodes() + NodeLimitFudgeFactor < unique()) { Compile::TracePhase tp(_t_renumberLive); igvn_worklist()->ensure_empty(); // should be done with igvn { @@ -3985,7 +3988,7 @@ void Compile::final_graph_reshaping_impl(Node *n, Final_Reshape_Counts& frc, Uni MemBarNode* mb = n->as_MemBar(); if (mb->trailing_store() || mb->trailing_load_store()) { assert(mb->leading_membar()->trailing_membar() == mb, "bad membar pair"); - Node* mem = BarrierSet::barrier_set()->barrier_set_c2()->step_over_gc_barrier(mb->in(MemBarNode::Precedent)); + Node* mem = mb->in(MemBarNode::Precedent); assert((mb->trailing_store() && mem->is_Store() && mem->as_Store()->is_release()) || (mb->trailing_load_store() && mem->is_LoadStore()), "missing mem op"); } else if (mb->leading()) { @@ -3999,10 +4002,7 @@ void Compile::final_graph_reshaping_impl(Node *n, Final_Reshape_Counts& frc, Uni "unused CallLeafPureNode should have been removed before final graph reshaping"); } #endif - bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->final_graph_reshaping(this, n, nop, dead_nodes); - if (!gc_handled) { - final_graph_reshaping_main_switch(n, frc, nop, dead_nodes); - } + final_graph_reshaping_main_switch(n, frc, nop, dead_nodes); // Collect CFG split points if (n->is_MultiBranch() && !n->is_RangeCheck()) { diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 20c50a074442..5938d6e73b9a 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -1651,11 +1651,6 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de return; // No need to redefine PointsTo node during first iteration. } int opcode = n->Opcode(); - bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_to_con_graph(this, igvn, delayed_worklist, n, opcode); - if (gc_handled) { - return; // Ignore node if already handled by GC. - } - if (n->is_Call()) { // Arguments to allocation and locking don't escape. if (n->is_AbstractLock()) { @@ -1891,10 +1886,6 @@ void ConnectionGraph::add_final_edges(Node *n) { ((n_ptn != nullptr) && (n_ptn->ideal_node() != nullptr)), "node should be registered already"); int opcode = n->Opcode(); - bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_final_edges(this, _igvn, n, opcode); - if (gc_handled) { - return; // Ignore node if already handled by GC. - } switch (opcode) { case Op_AddP: { Node* base = get_addp_base(n); @@ -2517,7 +2508,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { arg_has_oops && (i > TypeFunc::Parms); #ifdef ASSERT if (!(is_arraycopy || - BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(call) || (call->as_CallLeaf()->_name != nullptr && (strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 || strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 || @@ -3913,8 +3903,7 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) { bool ConnectionGraph::has_oop_node_outs(Node* n) { return n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) || n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) || - n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN) || - BarrierSet::barrier_set()->barrier_set_c2()->escape_has_out_with_unsafe_object(n); + n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN); } // Returns unique pointed java object or null. @@ -4685,9 +4674,7 @@ Node* ConnectionGraph::find_inst_mem(Node* orig_mem, int alias_idx, Unique_Node_ } } else if (proj_in->is_MemBar()) { // Check if there is an array copy for a clone - // Step over GC barrier when ReduceInitialCardMarks is disabled - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - Node* control_proj_ac = bs->step_over_gc_barrier(proj_in->in(0)); + Node* control_proj_ac = proj_in->in(0); if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) { // Stop if it is a clone @@ -5214,8 +5201,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, use->is_memory_access_intrinsic() || op == Op_SubTypeCheck || op == Op_InlineType || op == Op_FlatArrayCheck || op == Op_ReinterpretS2HF || - op == Op_ReachabilityFence || - BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(use))) { + op == Op_ReachabilityFence)) { n->dump(); use->dump(); assert(false, "EA: missing allocation reference path"); @@ -5401,8 +5387,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, (op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) { // They overwrite memory edge corresponding to destination array, memnode_worklist.push(use); - } else if (!(BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(use) || - use->is_memory_access_intrinsic() || op == Op_FlatArrayCheck)) { + } else if (!use->is_memory_access_intrinsic() && op != Op_FlatArrayCheck) { n->dump(); use->dump(); assert(false, "EA: missing memory path"); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 81b9fa501665..0e8ef7d98ba7 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -46,14 +46,17 @@ #include "opto/intrinsicnode.hpp" #include "opto/locknode.hpp" #include "opto/machnode.hpp" +#include "opto/memnode.hpp" #include "opto/multnode.hpp" #include "opto/narrowptrnode.hpp" #include "opto/opaquenode.hpp" +#include "opto/opcodes.hpp" #include "opto/parse.hpp" #include "opto/reachability.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" #include "opto/subtypenode.hpp" +#include "opto/type.hpp" #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" @@ -3919,41 +3922,10 @@ Node* GraphKit::gen_checkcast(Node* obj, Node* superklass, Node** failure_contro return res; } -Node* GraphKit::mark_word_test(Node* obj, uintptr_t mask_val, bool eq, bool check_lock) { +Node* GraphKit::mark_word_test(Node* obj, uintptr_t mask_val, bool eq) { // Load markword Node* mark_adr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); Node* mark = make_load(nullptr, mark_adr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); - if (check_lock && !UseCompactObjectHeaders) { - // COH: Locking does not override the markword with a tagged pointer. We can directly read from the markword. - // Check if obj is locked - Node* locked_bit = MakeConX(markWord::unlocked_value); - locked_bit = _gvn.transform(new AndXNode(locked_bit, mark)); - Node* cmp = _gvn.transform(new CmpXNode(locked_bit, MakeConX(0))); - Node* is_unlocked = _gvn.transform(new BoolNode(cmp, BoolTest::ne)); - IfNode* iff = new IfNode(control(), is_unlocked, PROB_MAX, COUNT_UNKNOWN); - _gvn.transform(iff); - Node* locked_region = new RegionNode(3); - Node* mark_phi = new PhiNode(locked_region, TypeX_X); - - // Unlocked: Use bits from mark word - locked_region->init_req(1, _gvn.transform(new IfTrueNode(iff))); - mark_phi->init_req(1, mark); - - // Locked: Load prototype header from klass - set_control(_gvn.transform(new IfFalseNode(iff))); - // Make loads control dependent to make sure they are only executed if array is locked - Node* klass_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); - Node* klass = _gvn.transform(LoadKlassNode::make(_gvn, C->immutable_memory(), klass_adr, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT)); - Node* proto_adr = basic_plus_adr(top(), klass, in_bytes(Klass::prototype_header_offset())); - Node* proto = _gvn.transform(LoadNode::make(_gvn, control(), C->immutable_memory(), proto_adr, proto_adr->bottom_type()->is_ptr(), TypeX_X, TypeX_X->basic_type(), MemNode::unordered)); - - locked_region->init_req(2, control()); - mark_phi->init_req(2, proto); - set_control(_gvn.transform(locked_region)); - record_for_igvn(locked_region); - - mark = mark_phi; - } // Now check if mark word bits are set Node* mask = MakeConX(mask_val); @@ -3964,7 +3936,7 @@ Node* GraphKit::mark_word_test(Node* obj, uintptr_t mask_val, bool eq, bool chec } Node* GraphKit::inline_type_test(Node* obj, bool is_inline) { - return mark_word_test(obj, markWord::inline_type_pattern, is_inline, /* check_lock = */ false); + return mark_word_test(obj, markWord::inline_type_pattern, is_inline); } Node* GraphKit::flat_array_test(Node* array_or_klass, bool flat) { @@ -4656,8 +4628,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) Node* valid_length_test = _gvn.intcon(1); if (ary_type->isa_aryptr()) { - BasicType bt = ary_type->isa_aryptr()->elem()->array_element_basic_type(); - jint max = TypeAryPtr::max_array_length(bt); + jint max = ary_type->is_aryptr()->max_array_length(); Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max))); valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le)); } @@ -4696,9 +4667,6 @@ AllocateNode* AllocateNode::Ideal_allocation(Node* ptr) { return nullptr; } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - ptr = bs->step_over_gc_barrier(ptr); - if (ptr->is_CheckCastPP()) { // strip only one raw-to-oop cast ptr = ptr->in(1); if (ptr == nullptr) return nullptr; @@ -4785,22 +4753,31 @@ void GraphKit::add_parse_predicate(Deoptimization::DeoptReason reason, const int // Add Parse Predicates which serve as placeholders to create new Runtime Predicates above them. All // Runtime Predicates inside a Runtime Predicate block share the same uncommon trap as the Parse Predicate. void GraphKit::add_parse_predicates(int nargs) { + if (!UseParsePredicates) { + return; + } + if (ShortRunningLongLoop) { // Will narrow the limit down with a cast node. Predicates added later may depend on the cast so should be last when // walking up from the loop. add_parse_predicate(Deoptimization::Reason_short_running_long_loop, nargs); } + if (UseLoopPredicate) { add_parse_predicate(Deoptimization::Reason_predicate, nargs); if (UseProfiledLoopPredicate) { add_parse_predicate(Deoptimization::Reason_profile_predicate, nargs); } } + if (UseAutoVectorizationPredicate) { add_parse_predicate(Deoptimization::Reason_auto_vectorization_check, nargs); } - // Loop Limit Check Predicate should be near the loop. - add_parse_predicate(Deoptimization::Reason_loop_limit_check, nargs); + + if (UseLoopLimitCheckPredicate) { + // Loop Limit Check Predicate should be near the loop. + add_parse_predicate(Deoptimization::Reason_loop_limit_check, nargs); + } } void GraphKit::sync_kit(IdealKit& ideal) { @@ -4871,51 +4848,81 @@ void GraphKit::store_String_coder(Node* str, Node* value) { value, TypeInt::BYTE, T_BYTE, IN_HEAP | MO_UNORDERED); } -// Capture src and dst memory state with a MergeMemNode -Node* GraphKit::capture_memory(const TypePtr* src_type, const TypePtr* dst_type) { +// If input and output memory types differ, capture the whole memory to preserve +// the dependency between preceding and subsequent loads/stores. +// For example, the following program: +// StoreB +// compress_string +// LoadB +// has this memory graph (use->def): +// LoadB -> compress_string -> CharMem +// ... -> StoreB -> ByteMem +// The intrinsic hides the dependency between LoadB and StoreB, causing +// the load to read from memory not containing the result of the StoreB. +// The correct memory graph should look like this: +// LoadB -> compress_string -> MergeMem -> StoreB +Node* GraphKit::capture_memory(const TypePtr*& combined_type, const TypePtr* src_type, const TypePtr* dst_type) { if (src_type == dst_type) { // Types are equal, we don't need a MergeMemNode + combined_type = src_type; return memory(src_type); } - MergeMemNode* merge = MergeMemNode::make(map()->memory()); - record_for_igvn(merge); // fold it up later, if possible - int src_idx = C->get_alias_index(src_type); - int dst_idx = C->get_alias_index(dst_type); - merge->set_memory_at(src_idx, memory(src_idx)); - merge->set_memory_at(dst_idx, memory(dst_idx)); - return merge; + Node* mem = reset_memory(); + set_all_memory(mem); + combined_type = TypePtr::BOTTOM; + return mem; +} + +// If dst_type and src_type are different, str may have an anti-dependency with another node +// consuming src_type. +// For example: +// compress_string +// StoreC +// has this memory graph (use->def): +// compress_string -> MergeMem -> CharMem +// StoreC +// The scheduler needs to ensure that compress_string is not executed after StoreC, or it will read +// the wrong memory. For normal loads, the scheduler computes its anti-dependencies to ensure the +// memory it reads from is not killed. Since we do not compute anti-dependencies for +// StrCompressedCopyNode, manually insert a MemBar so the anti-dependency becomes use-def +// dependency: +// StoreC -> MemBar -> MergeMem -> compress_string -> MergeMem -> CharMem +// --------------------------------> +void GraphKit::memory_effect(Node* res_mem, const TypePtr* src_type, const TypePtr* dst_type) { + set_memory(res_mem, dst_type); + if (src_type != dst_type) { + Node* all_mem = reset_memory(); + set_all_memory(all_mem); + Node* membar = new MemBarCPUOrderNode(C, C->get_alias_index(src_type), nullptr); + membar->init_req(TypeFunc::Control, control()); + membar->init_req(TypeFunc::Memory, all_mem); + membar = _gvn.transform(membar); + set_control(_gvn.transform(new ProjNode(membar, TypeFunc::Control))); + set_memory(_gvn.transform(new ProjNode(membar, TypeFunc::Memory)), src_type); + } } Node* GraphKit::compress_string(Node* src, const TypeAryPtr* src_type, Node* dst, Node* count) { assert(Matcher::match_rule_supported(Op_StrCompressedCopy), "Intrinsic not supported"); assert(src_type == TypeAryPtr::BYTES || src_type == TypeAryPtr::CHARS, "invalid source type"); - // If input and output memory types differ, capture both states to preserve - // the dependency between preceding and subsequent loads/stores. - // For example, the following program: - // StoreB - // compress_string - // LoadB - // has this memory graph (use->def): - // LoadB -> compress_string -> CharMem - // ... -> StoreB -> ByteMem - // The intrinsic hides the dependency between LoadB and StoreB, causing - // the load to read from memory not containing the result of the StoreB. - // The correct memory graph should look like this: - // LoadB -> compress_string -> MergeMem(CharMem, StoreB(ByteMem)) - Node* mem = capture_memory(src_type, TypeAryPtr::BYTES); - StrCompressedCopyNode* str = new StrCompressedCopyNode(control(), mem, src, dst, count); + const TypePtr* dst_type = TypeAryPtr::BYTES; + const TypePtr* adr_type; + Node* mem = capture_memory(adr_type, src_type, dst_type); + StrCompressedCopyNode* str = new StrCompressedCopyNode(control(), mem, adr_type, src, dst, count); Node* res_mem = _gvn.transform(new SCMemProjNode(_gvn.transform(str))); - set_memory(res_mem, TypeAryPtr::BYTES); + memory_effect(res_mem, src_type, dst_type); return str; } void GraphKit::inflate_string(Node* src, Node* dst, const TypeAryPtr* dst_type, Node* count) { assert(Matcher::match_rule_supported(Op_StrInflatedCopy), "Intrinsic not supported"); assert(dst_type == TypeAryPtr::BYTES || dst_type == TypeAryPtr::CHARS, "invalid dest type"); - // Capture src and dst memory (see comment in 'compress_string'). - Node* mem = capture_memory(TypeAryPtr::BYTES, dst_type); - StrInflatedCopyNode* str = new StrInflatedCopyNode(control(), mem, src, dst, count); - set_memory(_gvn.transform(str), dst_type); + const TypePtr* src_type = TypeAryPtr::BYTES; + const TypePtr* adr_type; + Node* mem = capture_memory(adr_type, src_type, dst_type); + StrInflatedCopyNode* str = new StrInflatedCopyNode(control(), mem, adr_type, src, dst, count); + Node* res_mem = _gvn.transform(str); + memory_effect(res_mem, src_type, dst_type); } void GraphKit::inflate_string_slow(Node* src, Node* dst, Node* start, Node* count) { diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index 59a95baa5e76..3fbef71c8952 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -844,7 +844,7 @@ class GraphKit : public Phase { bool maybe_larval = false); // Inline types - Node* mark_word_test(Node* obj, uintptr_t mask_val, bool eq, bool check_lock = true); + Node* mark_word_test(Node* obj, uintptr_t mask_val, bool eq); Node* inline_type_test(Node* obj, bool is_inline = true); Node* flat_array_test(Node* array_or_klass, bool flat = true); Node* null_free_array_test(Node* array, bool null_free = true); @@ -886,7 +886,8 @@ class GraphKit : public Phase { Node* load_String_coder(Node* str, bool set_ctrl); void store_String_value(Node* str, Node* value); void store_String_coder(Node* str, Node* value); - Node* capture_memory(const TypePtr* src_type, const TypePtr* dst_type); + Node* capture_memory(const TypePtr*& combined_type, const TypePtr* src_type, const TypePtr* dst_type); + void memory_effect(Node* res_mem, const TypePtr* src_type, const TypePtr* dst_type); Node* compress_string(Node* src, const TypeAryPtr* src_type, Node* dst, Node* count); void inflate_string(Node* src, Node* dst, const TypeAryPtr* dst_type, Node* count); void inflate_string_slow(Node* src, Node* dst, Node* start, Node* count); diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index ca7d812c08a9..92c3f66c861b 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -1880,6 +1880,19 @@ Node* IfNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* prev_dom = search_identical(dist, igvn); if (prev_dom != nullptr) { + Node* true_proj = this->true_proj(); + Node* false_proj = this->false_proj(); + + Node* head = true_proj->find_out_with(Op_Loop); + if (head == nullptr) { + head = false_proj->find_out_with(Op_Loop); + } + if (head != nullptr && head->as_Loop()->is_loop_nest_inner_loop()) { + // Exit test for a loop that's in the process of being transformed into a counted loop: do not remove that exit + // test so the counted loop transformation happens. + return nullptr; + } + // Dominating CountedLoopEnd (left over from some now dead loop) will become the new loop exit. Outer strip mined // loop will go away. Mark this loop as no longer strip mined. if (is_CountedLoopEnd()) { diff --git a/src/hotspot/share/opto/intrinsicnode.cpp b/src/hotspot/share/opto/intrinsicnode.cpp index d3e62dacfe80..887681233f16 100644 --- a/src/hotspot/share/opto/intrinsicnode.cpp +++ b/src/hotspot/share/opto/intrinsicnode.cpp @@ -63,8 +63,6 @@ const Type* StrIntrinsicNode::Value(PhaseGVN* phase) const { return bottom_type(); } -uint StrIntrinsicNode::size_of() const { return sizeof(*this); } - //============================================================================= //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out diff --git a/src/hotspot/share/opto/intrinsicnode.hpp b/src/hotspot/share/opto/intrinsicnode.hpp index d81e7bed7e96..1fe61cfb1785 100644 --- a/src/hotspot/share/opto/intrinsicnode.hpp +++ b/src/hotspot/share/opto/intrinsicnode.hpp @@ -48,7 +48,7 @@ class PartialSubtypeCheckNode : public Node { //------------------------------StrIntrinsic------------------------------- // Base class for Ideal nodes used in String intrinsic code. -class StrIntrinsicNode: public Node { +class StrIntrinsicNode : public Node { public: // Possible encodings of the parameters passed to the string intrinsic. // 'L' stands for Latin1 and 'U' stands for UTF16. For example, 'LU' means that @@ -59,7 +59,11 @@ class StrIntrinsicNode: public Node { protected: // Encoding of strings. Used to select the right version of the intrinsic. const ArgEncoding _encoding; - virtual uint size_of() const; + virtual uint size_of() const override { return sizeof(StrIntrinsicNode); } + virtual uint hash() const override { return Node::hash() + _encoding; } + virtual bool cmp(const Node& n) const override { + return Node::cmp(n) && _encoding == static_cast(n)._encoding; + } public: StrIntrinsicNode(Node* control, Node* char_array_mem, @@ -77,141 +81,189 @@ class StrIntrinsicNode: public Node { Node(control, char_array_mem, s1, s2), _encoding(encoding) { } - virtual const TypePtr* adr_type() const { return TypeAryPtr::BYTES; } - virtual uint match_edge(uint idx) const; - virtual uint ideal_reg() const { return Op_RegI; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); - virtual const Type* Value(PhaseGVN* phase) const; + virtual const TypePtr* adr_type() const override = 0; + virtual uint match_edge(uint idx) const override; + virtual uint ideal_reg() const override { return Op_RegI; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + virtual const Type* Value(PhaseGVN* phase) const override; ArgEncoding encoding() const { return _encoding; } private: - virtual bool depends_only_on_test_impl() const { return false; } + virtual bool depends_only_on_test_impl() const override { return false; } }; //------------------------------StrComp------------------------------------- -class StrCompNode: public StrIntrinsicNode { +class StrCompNode final : public StrIntrinsicNode { public: StrCompNode(Node* control, Node* char_array_mem, Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding): StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual const TypePtr* adr_type() const override { return TypeAryPtr::BYTES; } }; //------------------------------StrEquals------------------------------------- -class StrEqualsNode: public StrIntrinsicNode { +class StrEqualsNode final : public StrIntrinsicNode { public: StrEqualsNode(Node* control, Node* char_array_mem, Node* s1, Node* s2, Node* c, ArgEncoding encoding): StrIntrinsicNode(control, char_array_mem, s1, s2, c, encoding) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::BOOL; } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::BOOL; } + virtual const TypePtr* adr_type() const override { return TypeAryPtr::BYTES; } }; //------------------------------StrIndexOf------------------------------------- -class StrIndexOfNode: public StrIntrinsicNode { +class StrIndexOfNode final : public StrIntrinsicNode { public: StrIndexOfNode(Node* control, Node* char_array_mem, Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding): StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual const TypePtr* adr_type() const override { return TypeAryPtr::BYTES; } }; //------------------------------StrIndexOfChar------------------------------------- -class StrIndexOfCharNode: public StrIntrinsicNode { +class StrIndexOfCharNode final : public StrIntrinsicNode { public: StrIndexOfCharNode(Node* control, Node* char_array_mem, Node* s1, Node* c1, Node* c, ArgEncoding encoding): StrIntrinsicNode(control, char_array_mem, s1, c1, c, encoding) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual const TypePtr* adr_type() const override { return TypeAryPtr::BYTES; } }; //--------------------------StrCompressedCopy------------------------------- -class StrCompressedCopyNode: public StrIntrinsicNode { - public: - StrCompressedCopyNode(Node* control, Node* arymem, +class StrCompressedCopyNode final : public StrIntrinsicNode { +private: + const TypePtr* const _adr_type; + +public: + StrCompressedCopyNode(Node* control, Node* arymem, const TypePtr* adr_type, Node* s1, Node* s2, Node* c): - StrIntrinsicNode(control, arymem, s1, s2, c, none) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + StrIntrinsicNode(control, arymem, s1, s2, c, none), _adr_type(adr_type) {}; + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + +private: + virtual uint size_of() const override { return sizeof(StrCompressedCopyNode); } + virtual uint hash() const override { return StrIntrinsicNode::hash() + (uint)(uintptr_t) _adr_type; } + virtual bool cmp(const Node& n) const override { + return StrIntrinsicNode::cmp(n) && _adr_type == static_cast(n)._adr_type; + } + virtual const TypePtr* adr_type() const override { return _adr_type; } }; //--------------------------StrInflatedCopy--------------------------------- -class StrInflatedCopyNode: public StrIntrinsicNode { - public: - StrInflatedCopyNode(Node* control, Node* arymem, +class StrInflatedCopyNode final : public StrIntrinsicNode { +private: + const TypePtr* const _adr_type; + +public: + StrInflatedCopyNode(Node* control, Node* arymem, const TypePtr* adr_type, Node* s1, Node* s2, Node* c): - StrIntrinsicNode(control, arymem, s1, s2, c, none) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return Type::MEMORY; } - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + StrIntrinsicNode(control, arymem, s1, s2, c, none), _adr_type(adr_type) {}; + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return Type::MEMORY; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + +private: + virtual uint size_of() const override { return sizeof(StrInflatedCopyNode); } + virtual uint hash() const override { return StrIntrinsicNode::hash() + (uint)(uintptr_t) _adr_type; } + virtual bool cmp(const Node& n) const override { + return StrIntrinsicNode::cmp(n) && _adr_type == static_cast(n)._adr_type; + } + virtual const TypePtr* adr_type() const override { return _adr_type; } }; //------------------------------AryEq--------------------------------------- -class AryEqNode: public StrIntrinsicNode { - public: - AryEqNode(Node* control, Node* char_array_mem, +class AryEqNode final : public StrIntrinsicNode { +private: + const TypeAryPtr* const _in_adr_type; + +public: + AryEqNode(Node* control, Node* char_array_mem, const TypeAryPtr* in_adr_type, Node* s1, Node* s2, ArgEncoding encoding): - StrIntrinsicNode(control, char_array_mem, s1, s2, encoding) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::BOOL; } + StrIntrinsicNode(control, char_array_mem, s1, s2, encoding), _in_adr_type(in_adr_type) {}; + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::BOOL; } + +private: + virtual uint size_of() const override { return sizeof(AryEqNode); } + virtual uint hash() const override { return StrIntrinsicNode::hash() + (uint)(uintptr_t) _in_adr_type; } + virtual bool cmp(const Node& n) const override { + return StrIntrinsicNode::cmp(n) && _in_adr_type == static_cast(n)._in_adr_type; + } + virtual const TypePtr* adr_type() const override { return _in_adr_type; } }; //------------------------------CountPositives------------------------------ -class CountPositivesNode: public StrIntrinsicNode { +class CountPositivesNode final : public StrIntrinsicNode { public: CountPositivesNode(Node* control, Node* char_array_mem, Node* s1, Node* c1): StrIntrinsicNode(control, char_array_mem, s1, c1, none) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::POS; } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::POS; } + virtual const TypePtr* adr_type() const override { return TypeAryPtr::BYTES; } }; //------------------------------VectorizedHashCodeNode---------------------- -class VectorizedHashCodeNode: public Node { - public: - VectorizedHashCodeNode(Node* control, Node* ary_mem, Node* arg1, Node* cnt1, Node* result, Node* basic_type) - : Node(control, ary_mem, arg1, cnt1, result, basic_type) {}; - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } - virtual uint match_edge(uint idx) const; - virtual uint ideal_reg() const { return Op_RegI; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); - virtual const Type* Value(PhaseGVN* phase) const; +class VectorizedHashCodeNode final : public Node { +private: + const TypeAryPtr* const _in_adr_type; + +public: + VectorizedHashCodeNode(Node* control, Node* ary_mem, const TypeAryPtr* in_adr_type, Node* arg1, Node* cnt1, Node* result, Node* basic_type) + : Node(control, ary_mem, arg1, cnt1, result, basic_type), _in_adr_type(in_adr_type) {}; + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual uint match_edge(uint idx) const override; + virtual uint ideal_reg() const override { return Op_RegI; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + virtual const Type* Value(PhaseGVN* phase) const override; private: - virtual bool depends_only_on_test_impl() const { return false; } + virtual uint size_of() const override { return sizeof(VectorizedHashCodeNode); } + virtual uint hash() const override { return Node::hash() + (uint)(uintptr_t) _in_adr_type; } + virtual bool cmp(const Node& n) const override { + return Node::cmp(n) && _in_adr_type == static_cast(n)._in_adr_type; + } + virtual const TypePtr* adr_type() const override { return _in_adr_type; } + virtual bool depends_only_on_test_impl() const override { return false; } }; //------------------------------EncodeISOArray-------------------------------- // encode char[] to byte[] in ISO_8859_1 or ASCII -class EncodeISOArrayNode: public Node { +class EncodeISOArrayNode final : public Node { +private: + const TypePtr* const _adr_type; bool _ascii; - public: - EncodeISOArrayNode(Node* control, Node* arymem, Node* s1, Node* s2, Node* c, bool ascii) - : Node(control, arymem, s1, s2, c), _ascii(ascii) {} + +public: + EncodeISOArrayNode(Node* control, Node* arymem, const TypePtr* adr_type, Node* s1, Node* s2, Node* c, bool ascii) + : Node(control, arymem, s1, s2, c), _adr_type(adr_type), _ascii(ascii) {} bool is_ascii() { return _ascii; } - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } - virtual uint match_edge(uint idx) const; - virtual uint ideal_reg() const { return Op_RegI; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); - virtual const Type* Value(PhaseGVN* phase) const; - virtual uint size_of() const { return sizeof(EncodeISOArrayNode); } - virtual uint hash() const { return Node::hash() + _ascii; } - virtual bool cmp(const Node& n) const { - return Node::cmp(n) && _ascii == ((EncodeISOArrayNode&)n).is_ascii(); - } + virtual int Opcode() const override; + virtual const Type* bottom_type() const override { return TypeInt::INT; } + virtual uint match_edge(uint idx) const override; + virtual uint ideal_reg() const override { return Op_RegI; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + virtual const Type* Value(PhaseGVN* phase) const override; private: - virtual bool depends_only_on_test_impl() const { return false; } + virtual uint size_of() const override { return sizeof(EncodeISOArrayNode); } + virtual uint hash() const override { return Node::hash() + (uint)(uintptr_t) _adr_type + _ascii; } + virtual bool cmp(const Node& n) const override { + const EncodeISOArrayNode& e = static_cast(n); + return Node::cmp(n) && _ascii == e._ascii && _adr_type == e._adr_type; + } + virtual const TypePtr* adr_type() const override { return _adr_type; } + virtual bool depends_only_on_test_impl() const override { return false; } }; //-------------------------------DigitNode---------------------------------------- diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index bbe3d184c4de..7dc78e959b57 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1162,7 +1162,7 @@ bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) { Node* arg2 = argument(1); const TypeAryPtr* mtype = (ae == StrIntrinsicNode::UU) ? TypeAryPtr::CHARS : TypeAryPtr::BYTES; - set_result(_gvn.transform(new AryEqNode(control(), memory(mtype), arg1, arg2, ae))); + set_result(_gvn.transform(new AryEqNode(control(), memory(mtype), mtype, arg1, arg2, ae))); clear_upper_avx(); return true; @@ -4937,7 +4937,7 @@ bool LibraryCallKit::inline_getArrayProperties(ArrayPropertiesCheck check) { Node* bol; switch(check) { case IsFlat: - bol = flat_array_test(load_object_klass(array)); + bol = flat_array_test(array); break; case IsNullRestricted: bol = null_free_array_test(array); @@ -4947,8 +4947,7 @@ bool LibraryCallKit::inline_getArrayProperties(ArrayPropertiesCheck check) { // 1. If not flat, then atomic, or else... RegionNode* atomic_region = new RegionNode(1); RegionNode* non_atomic_region = new RegionNode(1); - Node* array_klass = load_object_klass(array); - Node* is_flat_bol = flat_array_test(array_klass); + Node* is_flat_bol = flat_array_test(array); IfNode* iff_is_flat = create_and_xform_if(control(), is_flat_bol, PROB_FAIR, COUNT_UNKNOWN); atomic_region->add_req(_gvn.transform(new IfFalseNode(iff_is_flat))); set_control(_gvn.transform(new IfTrueNode(iff_is_flat))); @@ -4957,6 +4956,7 @@ bool LibraryCallKit::inline_getArrayProperties(ArrayPropertiesCheck check) { Node* layout_kind = atomic_layout_array_test_and_get_layout_kind(array, atomic_region); // 3. ...if the element type is naturally atomic and null-free OR empty and nullable, then atomic, or else... + Node* array_klass = load_object_klass(array); int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); Node* array_element_klass_addr = off_heap_plus_addr(array_klass, element_klass_offset); Node* array_element_klass = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), array_element_klass_addr, _gvn.type(array_klass)->is_klassptr())); @@ -5263,7 +5263,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { if (Arguments::is_valhalla_enabled()) { // Handle inline type arrays // TODO 8251971 This is too strong - generate_fair_guard(flat_array_test(load_object_klass(original)), bailout); + generate_fair_guard(flat_array_test(original), bailout); generate_fair_guard(flat_array_test(refined_klass_node), bailout); generate_fair_guard(null_free_array_test(original), bailout); } @@ -5369,7 +5369,7 @@ bool LibraryCallKit::should_bail_out_on_non_ref_arrays(const TypeAryPtr* src_typ return true; } - if (UseArrayFlattening) { + if (!UseArrayFlattening) { // The remaining checks revolve around array flatness. Without array flatness, we don't need the stronger non-ref // runtime check excluding flat arrays. return false; @@ -5391,7 +5391,7 @@ bool LibraryCallKit::should_bail_out_on_non_ref_arrays(const TypeAryPtr* src_typ // TODO 8251971: Optimize for the case when flat src/dst are later found to not contain // oops (i.e., move this check to the macro expansion phase). BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - if (bs->array_copy_requires_gc_barriers(true, T_OBJECT, false, false, BarrierSetC2::Parsing)) { + if (!bs->array_copy_requires_gc_barriers(true, T_OBJECT, false, false, BarrierSetC2::Parsing)) { // No barriers required. return false; } @@ -6320,7 +6320,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { (ary_ptr == nullptr || (!ary_ptr->is_not_flat() && (!ary_ptr->is_flat() || ary_ptr->elem()->inline_klass()->contains_oops())))) { // Flat inline type array may have object field that would require a // write barrier. Conservatively, go to slow path. - generate_fair_guard(flat_array_test(obj_klass), slow_region); + generate_fair_guard(flat_array_test(obj), slow_region); } if (!stopped()) { @@ -7254,11 +7254,18 @@ bool LibraryCallKit::inline_encodeISOArray(bool ascii) { // 'src_start' points to src array + scaled offset // 'dst_start' points to dst array + scaled offset - const TypeAryPtr* mtype = TypeAryPtr::BYTES; - Node* enc = new EncodeISOArrayNode(control(), memory(mtype), src_start, dst_start, length, ascii); + // See GraphKit::compress_string + const TypePtr* src_adr_type = TypeAryPtr::get_array_body_type(src_elem); + const TypePtr* dst_adr_type = TypeAryPtr::get_array_body_type(dst_elem); + assert(src_adr_type == TypeAryPtr::BYTES || src_adr_type == TypeAryPtr::CHARS, "unexpected src_adr_type"); + assert(dst_adr_type == TypeAryPtr::BYTES, "unexpected dst_adr_type"); + const TypePtr* adr_type; + Node* mem = capture_memory(adr_type, src_adr_type, dst_adr_type); + Node* enc = new EncodeISOArrayNode(control(), mem, adr_type, src_start, dst_start, length, ascii); enc = _gvn.transform(enc); Node* res_mem = _gvn.transform(new SCMemProjNode(enc)); - set_memory(res_mem, mtype); + memory_effect(res_mem, src_adr_type, dst_adr_type); + set_result(enc); clear_upper_avx(); @@ -7737,7 +7744,8 @@ bool LibraryCallKit::inline_vectorizedHashCode() { // Resolve address of first element Node* array_start = array_element_address(array, offset, bt); - set_result(_gvn.transform(new VectorizedHashCodeNode(control(), memory(TypeAryPtr::get_array_body_type(bt)), + const TypeAryPtr* in_adr_type = TypeAryPtr::get_array_body_type(bt); + set_result(_gvn.transform(new VectorizedHashCodeNode(control(), memory(in_adr_type), in_adr_type, array_start, length, initialValue, basic_type))); clear_upper_avx(); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index bf461fc17a8a..d60001ad737d 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -222,8 +222,7 @@ Node *PhaseIdealLoop::get_early_ctrl_for_expensive(Node *n, Node* earliest) { if (nb_ctl_proj > 1) { break; } - assert(parent_ctl->is_Start() || parent_ctl->is_MemBar() || parent_ctl->is_Call() || - BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(parent_ctl), "unexpected node"); + assert(parent_ctl->is_Start() || parent_ctl->is_MemBar() || parent_ctl->is_Call(), "unexpected node"); assert(idom(ctl) == parent_ctl, "strange"); next = idom(parent_ctl); } @@ -706,9 +705,14 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, const Node* he } void PhaseIdealLoop::add_parse_predicates(IdealLoopTree* outer_ilt, LoopNode* inner_head, SafePointNode* cloned_sfpt) { + if (!UseParsePredicates) { + return; + } + if (ShortRunningLongLoop) { add_parse_predicate(Deoptimization::Reason_short_running_long_loop, inner_head, outer_ilt, cloned_sfpt); } + if (UseLoopPredicate) { add_parse_predicate(Deoptimization::Reason_predicate, inner_head, outer_ilt, cloned_sfpt); if (UseProfiledLoopPredicate) { @@ -720,7 +724,9 @@ void PhaseIdealLoop::add_parse_predicates(IdealLoopTree* outer_ilt, LoopNode* in add_parse_predicate(Deoptimization::Reason_auto_vectorization_check, inner_head, outer_ilt, cloned_sfpt); } - add_parse_predicate(Deoptimization::Reason_loop_limit_check, inner_head, outer_ilt, cloned_sfpt); + if (UseLoopLimitCheckPredicate) { + add_parse_predicate(Deoptimization::Reason_loop_limit_check, inner_head, outer_ilt, cloned_sfpt); + } } // If the loop has the shape of a counted loop but with a long @@ -5295,14 +5301,11 @@ void PhaseIdealLoop::build_and_optimize() { return; } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); // Nothing to do, so get out bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !do_max_unroll && - !do_expand_reachability_fences && !_verify_me && !_verify_only && - !bs->is_gc_specific_loop_opts_pass(_mode) ; + !do_expand_reachability_fences && !_verify_me && !_verify_only; bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); bool do_optimize_reachability_fences = OptimizeReachabilityFences && (C->reachability_fences_count() > 0); - bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(_mode); if (stop_early && !do_expensive_nodes && !do_optimize_reachability_fences) { return; } @@ -5379,7 +5382,7 @@ void PhaseIdealLoop::build_and_optimize() { // Given early legal placement, try finding counted loops. This placement // is good enough to discover most loop invariants. - if (!_verify_me && !_verify_only && !strip_mined_loops_expanded && !do_expand_reachability_fences) { + if (!_verify_me && !_verify_only && !do_expand_reachability_fences) { _ltree_root->counted_loop( this ); } @@ -5486,10 +5489,6 @@ void PhaseIdealLoop::build_and_optimize() { return; } - if (bs->optimize_loops(this, _mode, visited, nstack, worklist)) { - return; - } - if (ReassociateInvariants && !C->major_progress()) { // Reassociate invariants and prep for split_thru_phi for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { @@ -7184,7 +7183,7 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) { } // Try not to place code on a loop entry projection // which can inhibit range check elimination. - if (least != early && !BarrierSet::barrier_set()->barrier_set_c2()->is_gc_specific_loop_opts_pass(_mode)) { + if (least != early) { Node* ctrl_out = least->unique_ctrl_out_or_null(); if (ctrl_out != nullptr && ctrl_out->is_Loop() && least == ctrl_out->in(LoopNode::EntryControl) && diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 4f1f77ee8470..d81ac3b76368 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1124,9 +1124,9 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) { } // We can't use immutable memory for the flat array check because we are loading the mark word which is -// mutable. Although the bits we are interested in are immutable (we check for markWord::unlocked_value), -// we need to use raw memory to not break anti dependency analysis. Below code will attempt to still move -// flat array checks out of loops, mainly to enable loop unswitching. +// mutable. Although the bits we are interested in are immutable, we need to use raw memory to not break +// anti dependency analysis. The code below will attempt to still move flat array checks out of loops, +// mainly to enable loop unswitching. void PhaseIdealLoop::move_flat_array_check_out_of_loop(Node* n) { // Skip checks for more than one array if (n->req() > 3) { diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index ccf2cb0382ff..5421e490bc23 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -464,8 +464,6 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * values.at_put(j, mem); } else if (val->is_Store()) { Node* n = val->in(MemNode::ValueIn); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - n = bs->step_over_gc_barrier(n); if (is_subword_type(ft)) { n = Compile::narrow_value(ft, n, phi_type, &_igvn, true); } @@ -650,8 +648,6 @@ Node* PhaseMacroExpand::value_from_mem(Node* origin, Node* ctl, BasicType ft, co return value_from_alloc(ft, adr_t, alloc); } else if (mem->is_Store()) { Node* n = mem->in(MemNode::ValueIn); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - n = bs->step_over_gc_barrier(n); return n; } else if (mem->is_Phi()) { // attempt to produce a Phi reflecting the values on the input paths of the Phi @@ -805,7 +801,6 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode } while (can_eliminate && worklist.size() > 0) { - BarrierSetC2 *bs = BarrierSet::barrier_set()->barrier_set_c2(); res = worklist.pop(); for (DUIterator_Fast jmax, j = res->fast_outs(jmax); j < jmax && can_eliminate; j++) { Node* use = res->fast_out(j); @@ -827,7 +822,7 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode NOT_PRODUCT(fail_eliminate = "Mismatched access"); can_eliminate = false; } - if (!n->is_Store() && n->Opcode() != Op_CastP2X && !bs->is_gc_pre_barrier_node(n) && !reduce_merge_precheck) { + if (!n->is_Store() && n->Opcode() != Op_CastP2X && !reduce_merge_precheck) { DEBUG_ONLY(disq_node = n;) if (n->is_Load() || n->is_LoadStore()) { NOT_PRODUCT(fail_eliminate = "Field load";) @@ -3076,22 +3071,38 @@ void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) { _igvn.replace_node(check, C->top()); } -// FlatArrayCheckNode (array1 array2 ...) is expanded into: +// FlatArrayCheckNode inputs must be homogeneous: either all array inputs +// (array1 array2 ...) or all klass inputs (klass1 klass2 ...). +// +// For array inputs whose users are all If nodes, the check is expanded using +// mark words: // // long mark = array1.mark | array2.mark | ...; -// long locked_bit = markWord::unlocked_value & array1.mark & array2.mark & ...; -// if (locked_bit == 0) { -// // One array is locked, load prototype header from the klass -// mark = array1.klass.proto | array2.klass.proto | ... -// } // if ((mark & markWord::flat_array_bit_in_place) == 0) { -// ... +// ... +// } +// +// For klass inputs, and for array inputs with a non-If user, the check is +// expanded using the klass layout helpers. For array inputs, the klasses are +// loaded first: +// +// int layout = klass1.layout_helper | klass2.layout_helper | ...; +// if ((layout & Klass::_lh_array_tag_flat_value_bit_inplace) == 0) { +// ... // } void PhaseMacroExpand::expand_flatarraycheck_node(FlatArrayCheckNode* check) { - bool array_inputs = _igvn.type(check->in(FlatArrayCheckNode::ArrayOrKlass))->isa_oopptr() != nullptr; - if (array_inputs) { + bool use_mark_word = _igvn.type(check->in(FlatArrayCheckNode::ArrayOrKlass))->isa_oopptr() != nullptr; + Node* bol = check->unique_out(); + for (DUIterator_Fast imax, i = bol->fast_outs(imax); i < imax; i++) { + if (!bol->fast_out(i)->is_If()) { + // No control input, fall back to layout helper check + use_mark_word = false; + break; + } + } + + if (use_mark_word) { Node* mark = MakeConX(0); - Node* locked_bit = MakeConX(markWord::unlocked_value); Node* mem = check->in(FlatArrayCheckNode::Memory); for (uint i = FlatArrayCheckNode::ArrayOrKlass; i < check->req(); ++i) { Node* ary = check->in(i); @@ -3101,53 +3112,19 @@ void PhaseMacroExpand::expand_flatarraycheck_node(FlatArrayCheckNode* check) { Node* mark_adr = basic_plus_adr(ary, oopDesc::mark_offset_in_bytes()); Node* mark_load = _igvn.transform(LoadNode::make(_igvn, nullptr, mem, mark_adr, mark_adr->bottom_type()->is_ptr(), TypeX_X, TypeX_X->basic_type(), MemNode::unordered)); mark = _igvn.transform(new OrXNode(mark, mark_load)); - locked_bit = _igvn.transform(new AndXNode(locked_bit, mark_load)); } assert(!mark->is_Con(), "Should have been optimized out"); - Node* cmp = _igvn.transform(new CmpXNode(locked_bit, MakeConX(0))); - Node* is_unlocked = _igvn.transform(new BoolNode(cmp, BoolTest::ne)); - - // BoolNode might be shared, replace each if user - Node* old_bol = check->unique_out(); - assert(old_bol->is_Bool() && old_bol->as_Bool()->_test._test == BoolTest::ne, "unexpected condition"); - for (DUIterator_Last imin, i = old_bol->last_outs(imin); i >= imin; --i) { - IfNode* old_iff = old_bol->last_out(i)->as_If(); - Node* ctrl = old_iff->in(0); - RegionNode* region = new RegionNode(3); - Node* mark_phi = new PhiNode(region, TypeX_X); - - // Check if array is unlocked - IfNode* iff = _igvn.transform(new IfNode(ctrl, is_unlocked, PROB_MAX, COUNT_UNKNOWN))->as_If(); - - // Unlocked: Use bits from mark word - region->init_req(1, _igvn.transform(new IfTrueNode(iff))); - mark_phi->init_req(1, mark); - - // Locked: Load prototype header from klass - ctrl = _igvn.transform(new IfFalseNode(iff)); - Node* proto = MakeConX(0); - for (uint i = FlatArrayCheckNode::ArrayOrKlass; i < check->req(); ++i) { - Node* ary = check->in(i); - // Make loads control dependent to make sure they are only executed if array is locked - Node* klass_adr = basic_plus_adr(ary, oopDesc::klass_offset_in_bytes()); - Node* klass = _igvn.transform(LoadKlassNode::make(_igvn, C->immutable_memory(), klass_adr, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT)); - Node* proto_adr = basic_plus_adr(top(), klass, in_bytes(Klass::prototype_header_offset())); - Node* proto_load = _igvn.transform(LoadNode::make(_igvn, ctrl, C->immutable_memory(), proto_adr, proto_adr->bottom_type()->is_ptr(), TypeX_X, TypeX_X->basic_type(), MemNode::unordered)); - proto = _igvn.transform(new OrXNode(proto, proto_load)); - } - region->init_req(2, ctrl); - mark_phi->init_req(2, proto); - // Check if flat array bits are set - Node* mask = MakeConX(markWord::flat_array_bit_in_place); - Node* masked = _igvn.transform(new AndXNode(_igvn.transform(mark_phi), mask)); - cmp = _igvn.transform(new CmpXNode(masked, MakeConX(0))); - Node* is_not_flat = _igvn.transform(new BoolNode(cmp, BoolTest::eq)); + // Replace the bool node + assert(bol->is_Bool() && bol->as_Bool()->_test._test == BoolTest::ne, "unexpected condition"); + + // Check if flat array bits are set + Node* mask = MakeConX(markWord::flat_array_bit_in_place); + Node* masked = _igvn.transform(new AndXNode(mark, mask)); + Node* cmp = _igvn.transform(new CmpXNode(masked, MakeConX(0))); + Node* is_not_flat = _igvn.transform(new BoolNode(cmp, BoolTest::eq)); + _igvn.replace_node(bol, is_not_flat); - ctrl = _igvn.transform(region); - iff = _igvn.transform(new IfNode(ctrl, is_not_flat, PROB_MAX, COUNT_UNKNOWN))->as_If(); - _igvn.replace_node(old_iff, iff); - } _igvn.replace_node(check, C->top()); } else { // Fall back to layout helper check @@ -3170,18 +3147,16 @@ void PhaseMacroExpand::expand_flatarraycheck_node(FlatArrayCheckNode* check) { } Node* masked = transform_later(new AndINode(lhs, intcon(Klass::_lh_array_tag_flat_value_bit_inplace))); Node* cmp = transform_later(new CmpINode(masked, intcon(0))); - Node* bol = transform_later(new BoolNode(cmp, BoolTest::eq)); + Node* new_bol = transform_later(new BoolNode(cmp, BoolTest::eq)); Node* m2b = transform_later(new Conv2BNode(masked)); // The matcher expects the input to If/CMove nodes to be produced by a Bool(CmpI..) // pattern, but the input to other potential users (e.g. Phi) to be some // other pattern (e.g. a Conv2B node, possibly idealized as a CMoveI). - Node* old_bol = check->unique_out(); - for (DUIterator_Last imin, i = old_bol->last_outs(imin); i >= imin; --i) { - Node* user = old_bol->last_out(i); + for (DUIterator_Last imin, i = bol->last_outs(imin); i >= imin; --i) { + Node* user = bol->last_out(i); for (uint j = 0; j < user->req(); j++) { - Node* n = user->in(j); - if (n == old_bol) { - _igvn.replace_input_of(user, j, (user->is_If() || user->is_CMove()) ? bol : m2b); + if (user->in(j) == bol) { + _igvn.replace_input_of(user, j, (user->is_If() || user->is_CMove()) ? new_bol : m2b); } } } @@ -3304,8 +3279,7 @@ void PhaseMacroExpand::eliminate_macro_nodes(bool eliminate_locks) { n->is_OpaqueConstantBool() || n->is_OpaqueInitializedAssertionPredicate() || n->Opcode() == Op_MaxL || - n->Opcode() == Op_MinL || - BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(n), + n->Opcode() == Op_MinL, "unknown node type in macro list"); } if (C->failing()) { diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index 678c083f808f..a39f9a00337a 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -294,36 +294,13 @@ Node* PhaseMacroExpand::generate_nonpositive_guard(Node** ctrl, Node* index, boo } Node* PhaseMacroExpand::mark_word_test(Node** ctrl, Node* obj, MergeMemNode* mem, uintptr_t mask_val, RegionNode* region) { - // Load markword and check if obj is locked + // Load markword Node* mark = make_load_raw(nullptr, mem->memory_at(Compile::AliasIdxRaw), obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type()); - Node* locked_bit = MakeConX(markWord::unlocked_value); - locked_bit = transform_later(new AndXNode(locked_bit, mark)); - Node* cmp = transform_later(new CmpXNode(locked_bit, MakeConX(0))); - Node* is_unlocked = transform_later(new BoolNode(cmp, BoolTest::ne)); - IfNode* iff = transform_later(new IfNode(*ctrl, is_unlocked, PROB_MAX, COUNT_UNKNOWN))->as_If(); - Node* locked_region = transform_later(new RegionNode(3)); - Node* mark_phi = transform_later(new PhiNode(locked_region, TypeX_X)); - - // Unlocked: Use bits from mark word - locked_region->init_req(1, transform_later(new IfTrueNode(iff))); - mark_phi->init_req(1, mark); - - // Locked: Load prototype header from klass - *ctrl = transform_later(new IfFalseNode(iff)); - // Make loads control dependent to make sure they are only executed if array is locked - Node* klass_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); - Node* klass = transform_later(LoadKlassNode::make(_igvn, C->immutable_memory(), klass_adr, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT)); - Node* proto_adr = basic_plus_adr(top(), klass, in_bytes(Klass::prototype_header_offset())); - Node* proto = transform_later(LoadNode::make(_igvn, *ctrl, C->immutable_memory(), proto_adr, proto_adr->bottom_type()->is_ptr(), TypeX_X, TypeX_X->basic_type(), MemNode::unordered)); - - locked_region->init_req(2, *ctrl); - mark_phi->init_req(2, proto); - *ctrl = locked_region; // Now check if mark word bits are set Node* mask = MakeConX(mask_val); - Node* masked = transform_later(new AndXNode(mark_phi, mask)); - cmp = transform_later(new CmpXNode(masked, mask)); + Node* masked = transform_later(new AndXNode(mark, mask)); + Node* cmp = transform_later(new CmpXNode(masked, mask)); Node* bol = transform_later(new BoolNode(cmp, BoolTest::eq)); return generate_fair_guard(ctrl, bol, region); } @@ -1371,6 +1348,17 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { MergeMemNode* merge_mem = nullptr; if (ac->is_clonebasic()) { + // Flag the trailing MemBar so that optimize_simple_memory_chain knows it guards + // an expanded clone. clone_at_expansion virtual function may replace the ArrayCopyNode + // but does not set this flag. + Node* membar = ac->proj_out(TypeFunc::Control)->unique_ctrl_out(); + assert(membar->is_MemBar(), "expect MemBar after clonebasic"); + assert(membar->in(TypeFunc::Memory)->is_MergeMem() && + membar->in(TypeFunc::Memory)->as_MergeMem()->memory_at(Compile::AliasIdxRaw)->is_Proj() && + membar->in(TypeFunc::Memory)->as_MergeMem()->memory_at(Compile::AliasIdxRaw)->in(0) == ac, + "MemBar is from ac"); + membar->as_MemBar()->set_trailing_expanded_array_copy(); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); bs->clone_at_expansion(this, ac); return; @@ -1418,10 +1406,6 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { if (ac->_dest_type != TypeOopPtr::BOTTOM) { adr_type = ac->_dest_type->add_offset(Type::OffsetBot)->is_ptr(); } - if (ac->_src_type != ac->_dest_type) { - adr_type = TypeRawPtr::BOTTOM; - raw_base = true; - } } merge_mem = MergeMemNode::make(mem); transform_later(merge_mem); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 11d14cb090a4..1542d7c8d625 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -2143,10 +2143,7 @@ void Matcher::find_shared(Node* n) { // Now hack a few special opcodes uint opcode = n->Opcode(); - bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->matcher_find_shared_post_visit(this, n, opcode); - if (!gc_handled) { - find_shared_post_visit(n, opcode); - } + find_shared_post_visit(n, opcode); } else { ShouldNotReachHere(); @@ -2867,8 +2864,7 @@ bool Matcher::post_store_load_barrier(const Node* vmb) { xop == Op_CompareAndSwapL || xop == Op_CompareAndSwapP || xop == Op_CompareAndSwapN || - xop == Op_CompareAndSwapI || - BarrierSet::barrier_set()->barrier_set_c2()->matcher_is_store_load_barrier(x, xop)) { + xop == Op_CompareAndSwapI) { return true; } diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index dbd975200844..274b4d3e1106 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -806,9 +806,7 @@ ArrayCopyNode* MemNode::find_array_copy_clone(Node* ld_alloc, Node* mem) const { mb->in(0)->in(0) != nullptr && mb->in(0)->in(0)->is_ArrayCopy()) { ac = mb->in(0)->in(0)->as_ArrayCopy(); } else { - // Step over GC barrier when ReduceInitialCardMarks is disabled - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - Node* control_proj_ac = bs->step_over_gc_barrier(mb->in(0)); + Node* control_proj_ac = mb->in(0); if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) { ac = control_proj_ac->in(0)->as_ArrayCopy(); @@ -1270,9 +1268,6 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const { if (ac->as_ArrayCopy()->is_clonebasic()) { assert(ld_alloc != nullptr, "need an alloc"); assert(addp->is_AddP(), "address must be addp"); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - assert(bs->step_over_gc_barrier(addp->in(AddPNode::Base)) == bs->step_over_gc_barrier(ac->in(ArrayCopyNode::Dest)), "strange pattern"); - assert(bs->step_over_gc_barrier(addp->in(AddPNode::Address)) == bs->step_over_gc_barrier(ac->in(ArrayCopyNode::Dest)), "strange pattern"); addp->set_req(AddPNode::Base, src); addp->set_req(AddPNode::Address, src); } else { @@ -1543,8 +1538,6 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseValues* phase) const { (tp != nullptr) && tp->is_ptr_to_boxed_value()) { intptr_t ignore = 0; Node* base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ignore); - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - base = bs->step_over_gc_barrier(base); if (base != nullptr && base->is_Proj() && base->as_Proj()->_con == TypeFunc::Parms && base->in(0)->is_CallStaticJava() && @@ -2943,12 +2936,6 @@ Node* LoadNode::find_known_klass(PhaseGVN* phase) const { const TypeOopPtr* toop = phase->type(adr)->isa_oopptr(); if (toop == nullptr) { return nullptr; } - // Step over potential GC barrier for OopHandle resolve - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - if (bs->is_gc_barrier_node(base)) { - base = bs->step_over_gc_barrier(base); - } - // We can fetch the klass directly through an AllocateNode. // This works even if the klass is not constant (clone or newArray). if (offset == oopDesc::klass_offset_in_bytes()) { @@ -4780,6 +4767,36 @@ void MemBarNode::remove(PhaseIterGVN *igvn) { } } +#ifndef PRODUCT +void MemBarNode::dump_spec(outputStream* st) const { + switch (_kind) { + case Standalone: + st->print(" Standalone"); + break; + case TrailingLoad: + st->print(" TrailingLoad"); + break; + case TrailingStore: + st->print(" TrailingStore"); + break; + case LeadingStore: + st->print(" LeadingStore"); + break; + case TrailingLoadStore: + st->print(" TrailingLoadStore"); + break; + case LeadingLoadStore: + st->print(" LeadingLoadStore"); + break; + case TrailingExpandedArrayCopy: + st->print(" TrailingExpandedArrayCopy"); + break; + default: + fatal("Unimplemented MemBar kind: %d", _kind); + } +} +#endif // !PRODUCT + //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out // control copies diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 126acf4d0027..3a44757b8934 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -1284,6 +1284,10 @@ class MemBarNode: public MultiNode { static void set_load_store_pair(MemBarNode* leading, MemBarNode* trailing); void remove(PhaseIterGVN *igvn); + +#ifndef PRODUCT + virtual void dump_spec(outputStream *st) const; +#endif }; // "Acquire" - no following ref can move before (but earlier refs can diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 8dec62d73b32..305731f3d0c7 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -869,39 +869,30 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { } // Search for GraphKit::mark_word_test patterns and fold the test if the result is statically known - Node* load1 = in(1); - Node* load2 = nullptr; - if (load1->is_Phi() && phase->type(load1)->isa_long()) { - load1 = in(1)->in(1); - load2 = in(1)->in(2); - } - if (load1 != nullptr && load1->is_Load() && phase->type(load1)->isa_long() && - (load2 == nullptr || (load2->is_Load() && phase->type(load2)->isa_long()))) { - const TypePtr* adr_t1 = phase->type(load1->in(MemNode::Address))->isa_ptr(); - const TypePtr* adr_t2 = (load2 != nullptr) ? phase->type(load2->in(MemNode::Address))->isa_ptr() : nullptr; - if (adr_t1 != nullptr && adr_t1->offset() == oopDesc::mark_offset_in_bytes() && - (load2 == nullptr || (adr_t2 != nullptr && adr_t2->offset() == in_bytes(Klass::prototype_header_offset())))) { + if (in1->is_Load() && phase->type(in1)->isa_long()) { + const TypePtr* adr_t = phase->type(in1->in(MemNode::Address))->isa_ptr(); + if (adr_t != nullptr && adr_t->offset() == oopDesc::mark_offset_in_bytes()) { if (mask == markWord::inline_type_pattern) { - if (adr_t1->is_inlinetypeptr()) { + if (adr_t->is_inlinetypeptr()) { set_req_X(1, in(2), phase); return this; - } else if (!adr_t1->can_be_inline_type()) { + } else if (!adr_t->can_be_inline_type()) { set_req_X(1, phase->longcon(0), phase); return this; } } else if (mask == markWord::null_free_array_bit_in_place) { - if (adr_t1->is_null_free()) { + if (adr_t->is_null_free()) { set_req_X(1, in(2), phase); return this; - } else if (adr_t1->is_not_null_free()) { + } else if (adr_t->is_not_null_free()) { set_req_X(1, phase->longcon(0), phase); return this; } } else if (mask == markWord::flat_array_bit_in_place) { - if (adr_t1->is_flat()) { + if (adr_t->is_flat()) { set_req_X(1, in(2), phase); return this; - } else if (adr_t1->is_not_flat()) { + } else if (adr_t->is_not_flat()) { set_req_X(1, phase->longcon(0), phase); return this; } diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index be86ea3df124..7670e6ade89a 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -525,9 +525,6 @@ Node *Node::clone() const { C->add_template_assertion_predicate_opaque(n->as_OpaqueTemplateAssertionPredicate()); } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bs->register_potential_barrier_node(n); - n->set_idx(C->next_unique()); // Get new unique index as well NOT_PRODUCT(n->_igv_idx = C->next_igv_idx()); DEBUG_ONLY( n->verify_construction() ); @@ -659,8 +656,6 @@ void Node::destruct(PhaseValues* phase) { compile->remove_unstable_if_trap(as_CallStaticJava(), false); } } - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bs->unregister_potential_barrier_node(this); // See if the input array was allocated just prior to the object int edge_size = _max*sizeof(void*); @@ -1494,8 +1489,6 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) { igvn->add_users_to_worklist( n ); } else if (dead->is_data_proj_of_pure_function(n)) { igvn->_worklist.push(n); - } else { - BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, n); } } } diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 133744ee8bca..3d548e93eac1 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -2076,19 +2076,21 @@ void Parse::acmp_type_check(Node* input, const TypeOopPtr* tinput, ProfilePtrKin Node* null_ctl; Node* cast = acmp_null_check(input, tinput, input_ptr, null_ctl); - if (input_type != nullptr) { - Deoptimization::DeoptReason reason; - if (tinput->speculative_type() != nullptr && !too_many_traps_or_recompiles(Deoptimization::Reason_speculate_class_check)) { - reason = Deoptimization::Reason_speculate_class_check; + if (!stopped()) { + if (input_type != nullptr) { + Deoptimization::DeoptReason reason; + if (tinput->speculative_type() != nullptr && !too_many_traps_or_recompiles(Deoptimization::Reason_speculate_class_check)) { + reason = Deoptimization::Reason_speculate_class_check; + } else { + reason = Deoptimization::Reason_class_check; + } + acmp_type_check_or_trap(&cast, input_type, reason); } else { - reason = Deoptimization::Reason_class_check; + // No specific type, check for inline type + BuildCutout unless(this, inline_type_test(cast, /* is_inline = */ false), PROB_MAX); + inc_sp(2); + uncommon_trap_exact(Deoptimization::Reason_class_check, Deoptimization::Action_maybe_recompile); } - acmp_type_check_or_trap(&cast, input_type, reason); - } else { - // No specific type, check for inline type - BuildCutout unless(this, inline_type_test(cast, /* is_inline = */ false), PROB_MAX); - inc_sp(2); - uncommon_trap_exact(Deoptimization::Reason_class_check, Deoptimization::Action_maybe_recompile); } Node* ne_region = new RegionNode(2); diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 77c2fd27a50e..d816eeeb816e 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -675,16 +675,6 @@ ConNode* PhaseValues::zerocon(BasicType bt) { } - -//============================================================================= -Node* PhaseGVN::apply_ideal(Node* k, bool can_reshape) { - Node* i = BarrierSet::barrier_set()->barrier_set_c2()->ideal_node(this, k, can_reshape); - if (i == nullptr) { - i = k->Ideal(this, can_reshape); - } - return i; -} - Node* PhaseGVN::apply_identity(Node* n) { DEBUG_ONLY(uint old_unique = is_verify_IGVN_method_return() ? C->unique() : 0;) Node* const i = n->Identity(this); @@ -701,7 +691,7 @@ Node* PhaseGVN::transform(Node* n) { // Apply the Ideal call in a loop until it no longer applies Node* k = n; - Node* i = apply_ideal(k, /*can_reshape=*/false); + Node* i = k->Ideal(this, /*can_reshape=*/false); NOT_PRODUCT(uint loop_count = 1;) while (i != nullptr) { assert(i->_idx >= k->_idx, "Idealize should return new nodes, use Identity to return old nodes" ); @@ -711,7 +701,7 @@ Node* PhaseGVN::transform(Node* n) { dump_infinite_loop_info(i, "PhaseGVN::transform"); } #endif - i = apply_ideal(k, /*can_reshape=*/false); + i = k->Ideal(this, /*can_reshape=*/false); NOT_PRODUCT(loop_count++;) } NOT_PRODUCT(if (loop_count != 0) { set_progress(); }) @@ -1195,6 +1185,9 @@ bool PhaseIterGVN::deep_revisit() { } void PhaseIterGVN::optimize(bool deep) { + // A correctly handled failure returns at the failing() call that raised it, so + // the compilation must never get here failed, with the graph already flushed. + assert(!C->failing_internal(), "should not run IGVN on a failed compilation"); bool deep_revisit_converged = false; DEBUG_ONLY(_num_processed = 0;) NOT_PRODUCT(init_verifyPhaseIterGVN();) @@ -1909,23 +1902,6 @@ void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape, bool deep_revisit // test/jdk/jdk/incubator/vector/VectorRuns.java // -XX:VerifyIterativeGVN=1110 - // CallDynamicJavaNode::Ideal, and I think also for CallStaticJavaNode::Ideal - // and possibly their subclasses. - // During late inlining it can call CallJavaNode::register_for_late_inline - // That means we do more rounds of late inlining, but might fail. - // Then we do IGVN again, and register the node again for late inlining. - // This creates an endless cycle. Everytime we try late inlining, we - // are also creating more nodes, especially SafePoint and MergeMem. - // These nodes are immediately rejected when the inlining fails in the - // do_late_inline_check, but they still grow the memory, until we hit - // the MemLimit and crash. - // The assumption here seems that CallDynamicJavaNode::Ideal does not get - // called repeatedly, and eventually we terminate. I fear this is not - // a great assumption to make. We should investigate more. - // - // Found with: - // compiler/loopopts/superword/TestDependencyOffsets.java#vanilla-U - // -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 return; } @@ -2236,7 +2212,7 @@ Node *PhaseIterGVN::transform_old(Node* n) { DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) C->remove_modified_node(k); DEBUG_ONLY(uint hash_before = is_verify_IGVN_method_return() ? k->hash() : 0;) - Node* i = apply_ideal(k, /*can_reshape=*/true); + Node* i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); assert(!is_verify_IGVN_method_return() || k->outcnt() == 0 || i != nullptr || hash_before == k->hash(), "hash changed after Ideal returned nullptr for %s", k->Name()); @@ -2265,7 +2241,7 @@ Node *PhaseIterGVN::transform_old(Node* n) { DEBUG_ONLY(is_new = (k->outcnt() == 0);) C->remove_modified_node(k); DEBUG_ONLY(uint hash_before = is_verify_IGVN_method_return() ? k->hash() : 0;) - i = apply_ideal(k, /*can_reshape=*/true); + i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); assert(!is_verify_IGVN_method_return() || k->outcnt() == 0 || i != nullptr || hash_before == k->hash(), "hash changed after Ideal returned nullptr for %s", k->Name()); @@ -2388,8 +2364,6 @@ void PhaseIterGVN::remove_globally_dead_node(Node* dead, NodeOrigin origin) { } } else if (dead->is_data_proj_of_pure_function(in)) { _worklist.push(in); - } else { - BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(this, in); } if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory && in->is_Proj() && in->in(0) != nullptr && in->in(0)->is_Initialize()) { @@ -2551,16 +2525,6 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ } } - // AndLNode::Ideal folds GraphKit::mark_word_test patterns. Give it a chance to run. - if (n->is_Load() && use->is_Phi()) { - for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { - Node* u = use->fast_out(i); - if (u->Opcode() == Op_AndL) { - worklist.push(u); - } - } - } - uint use_op = use->Opcode(); if(use->is_Cmp()) { // Enable CMP/BOOL optimization add_users_to_worklist0(use, worklist); // Put Bool on worklist @@ -2830,9 +2794,6 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ // Loading the java mirror from a Klass requires two loads and the type // of the mirror load depends on the type of 'n'. See LoadNode::Value(). // LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror)))) - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bool has_load_barrier_nodes = bs->has_load_barrier_nodes(); - // Needed because of PhaseMacroExpand::expand_mh_intrinsic_return if (use_op == Op_CastP2X) { for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { @@ -2856,12 +2817,6 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ Node* u = use->fast_out(i2); const Type* ut = u->bottom_type(); if (u->Opcode() == Op_LoadP && ut->isa_instptr()) { - if (has_load_barrier_nodes) { - // Search for load barriers behind the load - add_users_to_worklist_if(worklist, u, [&](Node* b) { - return bs->is_gc_barrier_node(b); - }); - } worklist.push(u); } } @@ -3269,30 +3224,17 @@ void PhaseCCP::push_cast(Unique_Node_List& worklist, const Node* use) { // Loading the java mirror from a Klass requires two loads and the type of the mirror load depends on the type of 'n'. // See LoadNode::Value(). void PhaseCCP::push_loadp(Unique_Node_List& worklist, const Node* use) const { - BarrierSetC2* barrier_set = BarrierSet::barrier_set()->barrier_set_c2(); - bool has_load_barrier_nodes = barrier_set->has_load_barrier_nodes(); - if (use->Opcode() == Op_LoadP && use->bottom_type()->isa_rawptr()) { for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { Node* loadp = use->fast_out(i); const Type* ut = loadp->bottom_type(); if (loadp->Opcode() == Op_LoadP && ut->isa_instptr() && ut != type(loadp)) { - if (has_load_barrier_nodes) { - // Search for load barriers behind the load - push_load_barrier(worklist, barrier_set, loadp); - } worklist.push(loadp); } } } } -void PhaseCCP::push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use) { - add_users_to_worklist_if(worklist, use, [&](Node* u) { - return barrier_set->is_gc_barrier_node(u); - }); -} - // AndI/L::Value() optimizes patterns similar to (v << 2) & 3, or CON & 3 to zero if they are bitwise disjoint. // Add the AndI/L nodes back to the worklist to re-apply Value() in case the value is now a constant or shift // value changed. @@ -3650,8 +3592,6 @@ void Node::set_req_X( uint i, Node *n, PhaseIterGVN *igvn ) { default: break; } - - BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, old); } } diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 4e706f8c4783..c57529213933 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -448,9 +448,6 @@ class PhaseGVN : public PhaseValues { bool is_dominator(Node *d, Node *n) { return is_dominator_helper(d, n, true); } - // Helper to call Node::Ideal() and BarrierSetC2::ideal_node(). - Node* apply_ideal(Node* i, bool can_reshape); - // Helper to call Node::Identity() and verify that it returns an existing node. Node* apply_identity(Node* n); @@ -720,7 +717,6 @@ class PhaseCCP : public PhaseIterGVN { static void push_counted_loop_phi(Unique_Node_List& worklist, Node* parent, const Node* use); static void push_cast(Unique_Node_List& worklist, const Node* use); void push_loadp(Unique_Node_List& worklist, const Node* use) const; - static void push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use); void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const; diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp index cd0832cc062c..32c59edda315 100644 --- a/src/hotspot/share/opto/predicates.hpp +++ b/src/hotspot/share/opto/predicates.hpp @@ -816,22 +816,40 @@ class PredicateIterator : public StackObj { // Returns the entry to the earliest predicate. Node* for_each(PredicateVisitor& predicate_visitor) const { Node* current_node = _start_node; - PredicateBlockIterator loop_limit_check_predicate_iterator(current_node, Deoptimization::Reason_loop_limit_check); - current_node = loop_limit_check_predicate_iterator.for_each(predicate_visitor); + if (!UseParsePredicates) { + // We cannot do nothing when UseParsePredicates is not set: We could still have Assertion Predicates from Range + // Check Elimination even without Parse Predicates. We have one "generic" block, but we use + // Reason_loop_limit_check (could also use another predicate related reason) to not confuse the iteration logic + // with non-predicate deoptimization reasons. + return apply_for(predicate_visitor, current_node, Deoptimization::Reason_loop_limit_check); + } + + if (UseLoopLimitCheckPredicate) { + current_node = apply_for(predicate_visitor, current_node, Deoptimization::Reason_loop_limit_check); + } + if (UseAutoVectorizationPredicate) { - PredicateBlockIterator auto_vectorization_check_iterator(current_node, Deoptimization::Reason_auto_vectorization_check); - current_node = auto_vectorization_check_iterator.for_each(predicate_visitor); + current_node = apply_for(predicate_visitor, current_node, Deoptimization::Reason_auto_vectorization_check); } + if (UseLoopPredicate) { if (UseProfiledLoopPredicate) { - PredicateBlockIterator profiled_loop_predicate_iterator(current_node, Deoptimization::Reason_profile_predicate); - current_node = profiled_loop_predicate_iterator.for_each(predicate_visitor); + current_node = apply_for(predicate_visitor, current_node, Deoptimization::Reason_profile_predicate); } - PredicateBlockIterator loop_predicate_iterator(current_node, Deoptimization::Reason_predicate); - current_node = loop_predicate_iterator.for_each(predicate_visitor); + current_node = apply_for(predicate_visitor, current_node, Deoptimization::Reason_predicate); } - PredicateBlockIterator short_running_loop_predicate_iterator(current_node, Deoptimization::Reason_short_running_long_loop); - return short_running_loop_predicate_iterator.for_each(predicate_visitor); + + if (ShortRunningLongLoop) { + current_node = apply_for(predicate_visitor, current_node, Deoptimization::Reason_short_running_long_loop); + } + return current_node; + } + + private: + [[nodiscard]] static Node* apply_for(PredicateVisitor& predicate_visitor, Node* current_node, + Deoptimization::DeoptReason reason) { + PredicateBlockIterator predicate_block_iterator(current_node, reason); + return predicate_block_iterator.for_each(predicate_visitor); } }; diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index d45bfa235686..4ea516547029 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1070,12 +1070,6 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const { } static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n, bool& might_be_an_array) { - // Return the klass node for (indirect load from OopHandle) - // LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror)))) - // or null if not matching. - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - n = bs->step_over_gc_barrier(n); - if (n->Opcode() != Op_LoadP) return nullptr; const TypeInstPtr* tp = phase->type(n)->isa_instptr(); diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index b59b9b9bf532..3b3877f35daf 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -311,8 +311,8 @@ class CmpD3Node : public CmpDNode { }; //--------------------------FlatArrayCheckNode--------------------------------- -// Returns true if one of the input array objects or array klass ptrs (there -// can be multiple) is flat. +// Returns true if one of the inputs is flat. There can be multiple inputs, but +// all must be of the same kind: either array objects or array klass ptrs. class FlatArrayCheckNode : public CmpNode { public: enum { diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 7f39d1de985b..748c9298c2a0 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1537,6 +1537,78 @@ void Type::typerr( const Type *t ) const { ShouldNotReachHere(); } +#ifdef ASSERT +void Type::verify_meet_join() { + auto should_check = [](const Type* t1, const Type* t2) { + if (t1->base() > t2->base()) { + swap(t1, t2); + } + + switch (t1->base()) { + case Bottom: + case Top: + return true; + case Array: + case Interfaces: + case Tuple: + case Function: + return false; + case DoubleBot: + case DoubleCon: + case DoubleTop: + return t2->isa_double() != nullptr; + case FloatBot: + case FloatCon: + case FloatTop: + return t2->isa_float() != nullptr; + case HalfFloatBot: + case HalfFloatCon: + case HalfFloatTop: + return t2->isa_half_float() != nullptr; + case AnyPtr: + return t2->isa_ptr() != nullptr; + case OopPtr: + case InstPtr: + return t2->isa_oopptr() != nullptr; + case AryPtr: + // When UseCompressedOops is false, not all AryPtr instances agree on whether their elems + // are compressed (e.g. TypeAryPtr::NARROWOOPS and TypeAryPtr::OOPS) + return t2->isa_oopptr() != nullptr && UseCompressedOops; + case InstKlassPtr: + case AryKlassPtr: + return t2->isa_klassptr() != nullptr; + case VectorA: + case VectorS: + case VectorD: + case VectorX: + case VectorY: + case VectorZ: + case VectorMask: + return t1 == t2; + default: + return t1->base() == t2->base(); + } + }; + + ResourceMark rm; + const Dict* all_types = type_dict(); + GrowableArray all_types_snapshot(all_types->Size()); + for (DictI iter(all_types); iter.test(); ++iter) { + all_types_snapshot.append(static_cast(iter._key)); + } + + for (int i = 0; i < all_types_snapshot.length(); i++) { + const Type* t1 = all_types_snapshot.at(i); + for (int j = i; j < all_types_snapshot.length(); j++) { + const Type* t2 = all_types_snapshot.at(j); + if (should_check(t1, t2)) { + // This will invoke Type::check_fundamental_laws + t1->meet(t2); + } + } + } +} +#endif // ASSERT //============================================================================= // Convenience common pre-built types. @@ -3690,6 +3762,7 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* inter interfaces->verify_is_loaded(); } assert(instance_id != InstanceTop, "must not have top instance_id"); + assert(xk || instance_id == InstanceBot, "a known instance must have an exact type"); assert(ptr != Constant || instance_id == InstanceBot, "a constant cannot have an instance_id"); #endif if (Compile::current()->eliminate_boxing() && (t == InstPtr) && @@ -3898,10 +3971,16 @@ const Type* TypeOopPtr::xjoin_helper(const Type* t) const { case OopPtr: { const TypeOopPtr* tp = t->is_oopptr(); - int instance_id = join_instance_id(tp->instance_id()); const TypePtr* speculative = xjoin_speculative(tp); int depth = join_inline_depth(tp->inline_depth()); - return make(join_ptr(tp->ptr()), join_offset(tp->offset()), instance_id, speculative, depth); + + Offset offset = join_offset(tp->offset()); + if (offset == Offset::top) { + return TypePtr::make(AnyPtr, TopPTR, offset, speculative, depth); + } + + int instance_id = join_instance_id(tp->instance_id()); + return make(join_ptr(tp->ptr()), offset, instance_id, speculative, depth); } case InstPtr: @@ -4697,17 +4776,24 @@ const TypeAryPtr* TypeAryPtr::cast_to_instance_id(int instance_id) const { //-----------------------------max_array_length------------------------------- // A wrapper around arrayOopDesc::max_array_length(etype) with some input normalization. -jint TypeAryPtr::max_array_length(BasicType etype) { - if (!is_java_primitive(etype) && !::is_reference_type(etype)) { - if (etype == T_NARROWOOP) { - etype = T_OBJECT; - } else if (etype == T_ILLEGAL) { // bottom[] - etype = T_BYTE; // will produce conservatively high value - } else { - fatal("not an element type: %s", type2name(etype)); +jint TypeAryPtr::max_array_length() const { + if (is_not_flat()) { + BasicType etype = elem()->array_element_basic_type(); + if (!is_java_primitive(etype) && !::is_reference_type(etype)) { + if (etype == T_NARROWOOP) { + etype = T_OBJECT; + } else if (etype == T_ILLEGAL) { // bottom[] + etype = T_BYTE; // will produce conservatively high value + } else { + fatal("not an element type: %s", type2name(etype)); + } } + return arrayOopDesc::max_array_length(etype); + } else { + // A flat array's maximum length depends on its layout. If the layout + // is not known, max_jint is the only conservative upper bound. + return is_flat() && klass_is_exact() ? max_flat_elements() : max_jint; } - return arrayOopDesc::max_array_length(etype); } //-----------------------------narrow_size_type------------------------------- @@ -4717,7 +4803,7 @@ const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size) const { jint hi = size->_hi; jint lo = size->_lo; jint min_lo = 0; - jint max_hi = max_array_length(elem()->array_element_basic_type()); + jint max_hi = max_array_length(); //if (index_not_size) --max_hi; // type of a valid array index, FTR bool chg = false; if (lo < min_lo) { @@ -4967,7 +5053,7 @@ const Type* TypeAryPtr::xmeet_helper(const Type* t) const { int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR: - return this; + return make(ptr, const_oop(), ary(), klass(), klass_is_exact(), offset, field_offset(), instance_id(), speculative, depth, is_autobox_cache()); case BotPTR: case NotNull: return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); @@ -5455,9 +5541,10 @@ const Type* TypeMetadataPtr::xjoin(const Type* t) const { switch (t->base()) { case AnyPtr: { const TypePtr* tp = t->is_ptr(); - PTR ptr = join_ptr(tp->ptr()); Offset offset = join_offset(tp->offset()); - switch (tp->ptr()) { + PTR other_ptr = offset == Offset::top ? TopPTR : tp->ptr(); + PTR ptr = join_ptr(other_ptr); + switch (other_ptr) { case TopPTR: case Null: return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); @@ -5780,7 +5867,7 @@ const Type* TypeInstKlassPtr::xmeet(const Type* t) const { PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: - return this; + return make(ptr, instance_klass(), interfaces(), offset, flat_in_array()); case Null: if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); case AnyNull: @@ -5808,15 +5895,16 @@ const Type* TypeInstKlassPtr::xjoin(const Type* t) const { switch (t->base()) { case AnyPtr: { const TypePtr* tp = t->is_ptr(); - PTR ptr = join_ptr(tp->ptr()); Offset offset = join_offset(tp->offset()); - switch (tp->ptr()) { + PTR other_ptr = offset == Offset::top ? TopPTR : tp->ptr(); + PTR ptr = join_ptr(other_ptr); + switch (other_ptr) { case TopPTR: case Null: return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); case NotNull: case BotPTR: - return make(ptr, klass(), interfaces(), offset); + return make(ptr, klass(), interfaces(), offset, flat_in_array()); default: typerr(t); } @@ -6269,7 +6357,7 @@ const Type* TypeAryKlassPtr::xmeet(const Type* t) const { PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: - return this; + return make(ptr, elem(), klass(), offset, is_not_flat(), is_not_null_free(), is_flat(), is_null_free(), is_atomic(), is_refined_type()); case Null: if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); case AnyNull: @@ -6297,9 +6385,10 @@ const Type* TypeAryKlassPtr::xjoin(const Type* t) const { switch (t->base()) { case AnyPtr: { const TypePtr* tp = t->is_ptr(); - PTR ptr = join_ptr(tp->ptr()); Offset offset = join_offset(tp->offset()); - switch (tp->ptr()) { + PTR other_ptr = offset == Offset::top ? TopPTR : tp->ptr(); + PTR ptr = join_ptr(other_ptr); + switch (other_ptr) { case TopPTR: case Null: return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 15587dc740e7..aa25d0cc9eac 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -423,6 +423,8 @@ class Type { #endif // !PRODUCT [[noreturn]] void typerr(const Type *t) const; // Mixing types error + DEBUG_ONLY(static void verify_meet_join()); + // Create basic type static const Type* get_const_basic_type(BasicType type) { assert((uint)type <= T_CONFLICT && _const_basic_type[type] != nullptr, "bad type"); @@ -1818,7 +1820,7 @@ class TypeAryPtr : public TypeOopPtr { const TypeAryPtr* cast_to_autobox_cache() const; - static jint max_array_length(BasicType etype); + jint max_array_length() const; int flat_offset() const; const Offset field_offset() const { return _field_offset; } diff --git a/src/hotspot/share/opto/typejavaptr.hpp b/src/hotspot/share/opto/typejavaptr.hpp index 8c964cd77757..752c4324cae2 100644 --- a/src/hotspot/share/opto/typejavaptr.hpp +++ b/src/hotspot/share/opto/typejavaptr.hpp @@ -63,6 +63,11 @@ class TypeJavaPtrMeetHelper { Type::Offset offset = meet_offset(t1, t2); auto interfaces = meet_interfaces(t1, t2); auto flat_in_array = meet_flat_in_array(t1, t2); + // Due to value renumbering, types with the same instance_id may correspond to different + // allocations. As a result, we may encounter cases when instance_id is not InstanceBot, but + // the result is not an exact type, normalize instance_id to InstanceBot then. This is done in + // the callees of this function because here we do not know whether the types of the operands + // match. int instance_id = meet_instance_id(t1, t2); auto speculative = meet_speculative(t1, t2); int inline_depth = meet_inline_depth(t1, t2); @@ -70,7 +75,7 @@ class TypeJavaPtrMeetHelper { if (base1 != base2) { TypePtr::PTR ptr = t1->ptr() == TypePtr::BotPTR || t2->ptr() == TypePtr::BotPTR ? TypePtr::BotPTR : TypePtr::NotNull; return OopType::InstType::make(ptr, OopType::ciEnv::current()->Object_klass(), interfaces, false, nullptr, offset, - flat_in_array, instance_id, speculative, inline_depth); + flat_in_array, TypeOopPtr::InstanceBot, speculative, inline_depth); } else if (base1 == Type::InstPtr) { return instptr_type_xmeet(t1->is_instptr(), t2->is_instptr(), offset, interfaces, flat_in_array, instance_id, speculative, inline_depth); } else { @@ -89,6 +94,10 @@ class TypeJavaPtrMeetHelper { ConstOopType const_oop = nullptr; meet_ptr_and_const_oop(ptr, const_oop, t1, t2); bool xk = t1->klass_is_exact() && t2->klass_is_exact() && k1 == k2; + if (!xk) { + // See oopptr_type_xmeet + instance_id = TypeOopPtr::InstanceBot; + } // Consider an unloaded class to be a direct child of j.l.O and not have any subclass decltype(k1) k; @@ -130,6 +139,11 @@ class TypeJavaPtrMeetHelper { bool xk = t1->klass_is_exact() && t2->klass_is_exact() && !aryptr_klass_disjoint(t1, t2); auto field_offset = t1->field_offset().meet(t2->field_offset()); bool autobox_cache = t1->is_autobox_cache() && t2->is_autobox_cache(); + + if (!xk) { + // See oopptr_type_xmeet + instance_id = TypeOopPtr::InstanceBot; + } return AryOopType::make(ptr, const_oop, ary, klass, xk, offset, field_offset, instance_id, speculative, inline_depth, autobox_cache); } @@ -246,8 +260,13 @@ class TypeJavaPtrMeetHelper { template static TypePtr::PTR meet_ary_klass_ptr(const AryKlassType* t1, const AryKlassType* t2) { + // Sometimes, the klass is computed and cached, sometimes it is not. In general, the only time + // we need to compare klass() is when t1->elem() and t2->elem() are both TypeInt::INT. In other + // cases, it is fine if klass_match == true, other parameters must reveal if t1 and t2 are not + // of the same type. + bool klass_match = t1->klass() == nullptr || t2->klass() == nullptr || t1->klass() == t2->klass(); if (t1->ptr() == TypePtr::Constant && t2->ptr() == TypePtr::Constant && - t1->elem() == t2->elem() && t1->klass() == t2->klass() && + t1->elem() == t2->elem() && klass_match && t1->is_not_flat() == t2->is_not_flat() && t1->is_not_null_free() == t2->is_not_null_free() && t1->is_flat() == t2->is_flat() && t1->is_null_free() == t2->is_null_free() && t1->is_atomic() == t2->is_atomic() && t1->is_refined_type() == t2->is_refined_type()) { @@ -336,7 +355,8 @@ class TypeJavaPtrMeetHelper { if (both_are_exact) { return exact_klass != other_klass || exact_type->interfaces() != other_type->interfaces(); } else { - return !exact_klass->is_subtype_of(other_klass) || !exact_type->interfaces()->contains(other_type->interfaces()); + return !other_klass->is_loaded() || !exact_klass->is_subtype_of(other_klass) || + !exact_type->interfaces()->contains(other_type->interfaces()); } } diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index d04eda60b81d..f1857409455a 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -1680,16 +1680,22 @@ bool LibraryCallKit::inline_vector_test() { } Node* opd1 = unbox_vector(argument(4), vbox_type, elem_bt, num_elem); + if (opd1 == nullptr) { + log_if_needed(" ** unbox failed m1=%s", NodeClassNames[argument(4)->Opcode()]); + return false; + } + Node* opd2; if (Matcher::vectortest_needs_second_argument(booltest == BoolTest::overflow, opd1->bottom_type()->isa_pvectmask())) { opd2 = unbox_vector(argument(5), vbox_type, elem_bt, num_elem); + if (opd2 == nullptr) { + log_if_needed(" ** unbox failed m2=%s", NodeClassNames[argument(5)->Opcode()]); + return false; + } } else { opd2 = opd1; } - if (opd1 == nullptr || opd2 == nullptr) { - return false; // operand unboxing failed - } Node* cmp = gvn().transform(trace_vector(new VectorTestNode(opd1, opd2, booltest))); BoolTest::mask test = Matcher::vectortest_mask(booltest == BoolTest::overflow, diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 45ff6a7ffa24..4bc95eec13fc 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1281,6 +1281,10 @@ Node* VectorNode::make_scalar(Compile* c, int vopc, BasicType bt, Node* control, return new AndINode(in1, in2); case Op_AndL: return new AndLNode(in1, in2); + case Op_DivI: + return new DivINode(control, in1, in2); + case Op_DivL: + return new DivLNode(control, in1, in2); case Op_DivF: return new DivFNode(control, in1, in2); case Op_DivD: diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 4395df835f81..da92cffe5c7b 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -808,6 +808,7 @@ JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle)) Handle ho(THREAD, obj); args.push_oop(ho); methodHandle method(THREAD, Universe::value_object_hash_code_method()); + method->method_holder()->initialize(CHECK_0); // Ensure class ValueObjectMethods is initialized JavaCalls::call(&result, method, &args, THREAD); Exceptions::wrap_exception_in_internal_error("Internal error in hashCode", CHECK_0); @@ -825,7 +826,7 @@ JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle)) current_mark = ho->mark(); new_mark = current_mark.copy_set_hash(identity_hash); old_mark = ho->cas_set_mark(new_mark, current_mark); - assert(old_mark.has_no_hash() || old_mark.hash() == new_mark.hash(), + assert(!old_mark.has_hash() || old_mark.hash() == new_mark.hash(), "CAS identity hash invariant violated, expected=" INTPTR_FORMAT " actual=" INTPTR_FORMAT, new_mark.hash(), old_mark.hash()); @@ -833,7 +834,7 @@ JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle)) return checked_cast(new_mark.hash()); } else { - return checked_cast(ObjectSynchronizer::FastHashCode(THREAD, obj)); + return checked_cast(obj->identity_hash(THREAD)); } JVM_END diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 389ac7f43688..13325523684b 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1545,7 +1545,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec GrowableArray* wantList = nullptr; ObjectMonitor* mon = mark.has_monitor() - ? ObjectSynchronizer::read_monitor(hobj(), mark) + ? ObjectSynchronizer::read_monitor(hobj()) : nullptr; if (mon != nullptr) { diff --git a/src/hotspot/share/prims/jvmtiTagMapTable.cpp b/src/hotspot/share/prims/jvmtiTagMapTable.cpp index f16bd79d2174..c1992e308ce8 100644 --- a/src/hotspot/share/prims/jvmtiTagMapTable.cpp +++ b/src/hotspot/share/prims/jvmtiTagMapTable.cpp @@ -244,11 +244,9 @@ jlong* JvmtiTagMapTable::lookup(const JvmtiHeapwalkObject& obj) const { return nullptr; } - if (!obj.is_value()) { - if (obj.obj()->fast_no_hash_check()) { - // Objects in the table all have a hashcode, unless inlined types. - return nullptr; - } + if (!obj.is_value() && !obj.obj()->has_identity_hash()) { + // Objects in the table all have a hashcode, unless inlined types. + return nullptr; } JvmtiTagMapKey entry(&obj); jlong* found = _table.get(entry); @@ -265,7 +263,7 @@ void JvmtiTagMapTable::add(const JvmtiHeapwalkObject& obj, jlong tag) { assert(!obj.is_flat(), "Cannot add flat object to JvmtiTagMapTable"); JvmtiTagMapKey new_entry(&obj); bool is_added; - if (!obj.is_value() && obj.obj()->fast_no_hash_check()) { + if (!obj.is_value() && !obj.obj()->has_identity_hash()) { // Can't be in the table so add it fast. is_added = _table.put_when_absent(new_entry, tag); } else { diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 7e9a97410bca..a4578cf46f03 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -2187,6 +2187,22 @@ WB_ENTRY(jobject, WB_printMethods(JNIEnv* env, jobject wb, jstring class_name_pa return result; WB_END +WB_ENTRY(jint, WB_GetMarkWordOffset(JNIEnv* env, jobject o)) + return oopDesc::mark_offset_in_bytes(); +WB_END + +WB_ENTRY(jlong, WB_GetInlineTypePattern(JNIEnv* env, jobject o)) + return markWord::inline_type_pattern; +WB_END + +WB_ENTRY(jlong, WB_GetNullFreeArrayBitInPlace(JNIEnv* env, jobject o)) + return markWord::null_free_array_bit_in_place; +WB_END + +WB_ENTRY(jlong, WB_GetFlatArrayBitInPlace(JNIEnv* env, jobject o)) + return markWord::flat_array_bit_in_place; +WB_END + WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs)) VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE); VMThread::execute(&clear_ics); @@ -3103,6 +3119,10 @@ static JNINativeMethod methods[] = { {CC"getIndyCPIndex0", CC"(Ljava/lang/Class;I)I", (void*)&WB_getIndyCPIndex}, {CC"printClasses0", CC"(Ljava/lang/String;I)Ljava/lang/String;", (void*)&WB_printClasses}, {CC"printMethods0", CC"(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;", (void*)&WB_printMethods}, + {CC"getMarkWordOffset", CC"()I", (void*)&WB_GetMarkWordOffset}, + {CC"getInlineTypePattern", CC"()J", (void*)&WB_GetInlineTypePattern}, + {CC"getNullFreeArrayBitInPlace", CC"()J", (void*)&WB_GetNullFreeArrayBitInPlace}, + {CC"getFlatArrayBitInPlace", CC"()J", (void*)&WB_GetFlatArrayBitInPlace}, {CC"getMethodBooleanOption", CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", (void*)&WB_GetMethodBooleaneOption}, diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 37c5815f60e3..702909409a76 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "runtime/os.hpp" #include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" const char* Abstract_VM_Version::_s_vm_release = Abstract_VM_Version::vm_release(); const char* Abstract_VM_Version::_s_internal_vm_info_string = Abstract_VM_Version::internal_vm_info_string(); @@ -140,31 +141,28 @@ const char* Abstract_VM_Version::vm_vendor() { // The VM info string should be a constant, but its value cannot be finalized until after VM arguments -// have been fully processed. And we want to avoid dynamic memory allocation which will cause ASAN -// report error, so we enumerate all the cases by static const string value. +// have been fully processed. The result is C-heap allocated, and should be freed by the caller. const char* Abstract_VM_Version::vm_info_string() { + stringStream ss; switch (Arguments::mode()) { - case Arguments::_int: - if (is_vm_statically_linked()) { - return CDSConfig::is_using_archive() ? "interpreted mode, static, sharing" : "interpreted mode, static"; - } else { - return CDSConfig::is_using_archive() ? "interpreted mode, sharing" : "interpreted mode"; - } - case Arguments::_mixed: - if (is_vm_statically_linked()) { - return CDSConfig::is_using_archive() ? "mixed mode, static, sharing" : "mixed mode, static"; - } else { - return CDSConfig::is_using_archive() ? "mixed mode, sharing" : "mixed mode"; - } - case Arguments::_comp: - if (is_vm_statically_linked()) { - return CDSConfig::is_using_archive() ? "compiled mode, static, sharing" : "compiled mode, static"; - } else { - return CDSConfig::is_using_archive() ? "compiled mode, sharing" : "compiled mode"; - } + case Arguments::_int: ss.print("%s", "interpreted mode"); break; + case Arguments::_mixed: ss.print("%s", "mixed mode"); break; + case Arguments::_comp: ss.print("%s", "compiled mode"); break; + default: ShouldNotReachHere(); } - ShouldNotReachHere(); - return ""; + + if (is_vm_statically_linked()) { + ss.print("%s", ", static"); + } + if (CDSConfig::is_dumping_preimage_static_archive()) { + ss.print("%s", ", aot training"); + } else if (CDSConfig::is_dumping_final_static_archive()) { + ss.print("%s", ", aot assembly"); + } else if (CDSConfig::is_using_archive()) { + ss.print("%s", CDSConfig::new_aot_flags_used() ? ", aot production" : ", sharing"); + } + + return ss.as_string(/*c_heap=*/true); } // NOTE: do *not* use stringStream. this function is called by diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 003e2d0fbfa4..cff14087d75c 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -400,7 +400,9 @@ void Arguments::init_system_properties() { PropertyList_add(&_system_properties, new SystemProperty("jdk.debug", VM_Version::jdk_debug_level(), false)); // Initialize the vm.info now, but it will need updating after argument parsing. - _vm_info = new SystemProperty("java.vm.info", VM_Version::vm_info_string(), true); + const char* vm_info_str = VM_Version::vm_info_string(); + _vm_info = new SystemProperty("java.vm.info", vm_info_str, true); + FREE_C_HEAP_ARRAY(vm_info_str); // Following are JVMTI agent writable properties. // Properties values are set to nullptr and they are @@ -1347,8 +1349,10 @@ void Arguments::set_mode_flags(Mode mode) { // Ensure Agent_OnLoad has the correct initial values. // This may not be the final mode; mode may change later in onload phase. + const char* vm_info_str = VM_Version::vm_info_string(); PropertyList_unique_add(&_system_properties, "java.vm.info", - VM_Version::vm_info_string(), AddProperty, UnwriteableProperty, ExternalProperty); + vm_info_str, AddProperty, UnwriteableProperty, ExternalProperty); + FREE_C_HEAP_ARRAY(vm_info_str); UseInterpreter = true; UseCompiler = true; @@ -3602,6 +3606,37 @@ jint Arguments::apply_ergo() { warning("Disabling UseProfiledLoopPredicate since UseLoopPredicate is turned off."); FLAG_SET_ERGO(UseProfiledLoopPredicate, false); } + + bool any_parse_predicate_flag_enabled = UseLoopLimitCheckPredicate || + UseAutoVectorizationPredicate || + UseLoopPredicate || + UseProfiledLoopPredicate || + ShortRunningLongLoop; + + if (!UseParsePredicates && any_parse_predicate_flag_enabled) { + // Disable any Parse Predicate enabling flag when UseParsePredicates is not set. + FLAG_SET_ERGO(UseLoopLimitCheckPredicate, false); + FLAG_SET_ERGO(UseLoopPredicate, false); + FLAG_SET_ERGO(UseProfiledLoopPredicate, false); + FLAG_SET_ERGO(UseAutoVectorizationPredicate, false); + FLAG_SET_ERGO(ShortRunningLongLoop, false); + + if ((!FLAG_IS_DEFAULT(UseLoopLimitCheckPredicate) && UseLoopLimitCheckPredicate) || + (!FLAG_IS_DEFAULT(UseAutoVectorizationPredicate) && UseAutoVectorizationPredicate) || + (!FLAG_IS_DEFAULT(UseLoopPredicate) && UseLoopPredicate) || + (!FLAG_IS_DEFAULT(UseProfiledLoopPredicate) && UseProfiledLoopPredicate) || + (!FLAG_IS_DEFAULT(ShortRunningLongLoop) && ShortRunningLongLoop)) { + warning("Disabling UseParsePredicates disables all Parse Predicate enabling flags: UseLoopLimitCheckPredicate," + " UseLoopPredicate, UseProfiledLoopPredicate, UseAutoVectorizationPredicate, and ShortRunningLongLoop"); + } + + } + + if (UseParsePredicates && !any_parse_predicate_flag_enabled) { + warning("Disabling UseParsePredicates because all Parse Predicate flags are disabled: UseLoopLimitCheckPredicate," + " UseLoopPredicate, UseProfiledLoopPredicate, UseAutoVectorizationPredicate, and ShortRunningLongLoop"); + FLAG_SET_ERGO(UseParsePredicates, false); + } #endif // COMPILER2 if (log_is_enabled(Info, perf, class, link)) { diff --git a/src/hotspot/share/runtime/basicLock.cpp b/src/hotspot/share/runtime/basicLock.cpp index 73f9cc94b0aa..03d576ae5729 100644 --- a/src/hotspot/share/runtime/basicLock.cpp +++ b/src/hotspot/share/runtime/basicLock.cpp @@ -38,7 +38,7 @@ void BasicLock::print_on(outputStream* st, oop owner) const { void BasicLock::move_to(oop obj, BasicLock* dest) { // Check to see if we need to inflate the lock. This is only needed // if an object is locked using "this" lightweight monitor. In that - // case, the displaced_header() is unlocked/neutral, because the + // case, the displaced_header() is lock-neutral, because the // displaced_header() contains the header for the originally unlocked // object. However the lock could have already been inflated. But it // does not matter, this inflation will just be a no-op. For other cases, diff --git a/src/hotspot/share/runtime/basicLock.hpp b/src/hotspot/share/runtime/basicLock.hpp index 26d1c2e762a8..ed580510aaf2 100644 --- a/src/hotspot/share/runtime/basicLock.hpp +++ b/src/hotspot/share/runtime/basicLock.hpp @@ -31,6 +31,8 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/sizes.hpp" +class ObjectMonitor; + class BasicLock { friend class VMStructs; private: diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index a0d304fe1584..e633d12278b8 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1500,10 +1500,9 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArrayowner()->is_locked(), "object must be locked now"); assert(obj->mark().has_monitor(), "must be"); assert(!deoptee_thread->lock_stack().contains(obj()), "must be"); - assert(ObjectSynchronizer::read_monitor(obj(), obj->mark())->has_owner(deoptee_thread), "must be"); + assert(ObjectSynchronizer::read_monitor(obj())->has_owner(deoptee_thread), "must be"); } } } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index edfcf2e53629..5288c6584b4b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -521,10 +521,10 @@ const int ObjectAlignmentInBytes = 8; product(bool, CreateCoredumpOnCrash, true, \ "Create core/mini dump on VM fatal error") \ \ - product(uint64_t, ErrorLogTimeout, 2 * 60, \ + product(uint, ErrorLogTimeout, 2 * 60, \ "Timeout, in seconds, to limit the time spent on writing an " \ - "error log in case of a crash.") \ - range(0, (uint64_t)max_jlong/1000) \ + "error log in case of a crash. A value of 0 disables the " \ + "timeout.") \ \ product(bool, ErrorLogSecondaryErrorDetails, false, DIAGNOSTIC, \ "If enabled, show details on secondary crashes in the error log") \ diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 7809e66058fb..be5478829f07 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -104,7 +104,9 @@ class ThreadStateTransition : public StackObj { thread->set_thread_state(_thread_in_vm); } SafepointMechanism::process_if_requested_with_exit_check(thread, to != _thread_in_Java ? false : check_asyncs); - thread->set_thread_state(to); + if (to != _thread_in_vm) { + thread->set_thread_state(to); + } } static inline void transition_from_vm(JavaThread *thread, JavaThreadState to, bool check_asyncs = true) { diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 8578dd171ee8..084269a530c5 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -380,6 +380,12 @@ void before_exit(JavaThread* thread, bool halt) { Events::log(thread, "Before exit entered"); + // A GC requested after we shut down the heap blocks that requesting Java thread. + // Suppress GC-a-lot for threads entering shutdown as Monitor::lock() calls in the + // remainder of the shutdown sequence could otherwise block when executing a + // GC-a-lot caused collection. + NOT_PRODUCT(thread->set_skip_gcalot(true);) + // Note: don't use a Mutex to guard the entire before_exit(), as // JVMTI post_thread_end_event and post_vm_death_event will run native code. // A CAS or OSMutex would work just fine but then we need to manipulate diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index fc593b7f4364..90b6a256715e 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -281,7 +281,7 @@ void JavaThread::check_possible_safepoint() { #endif // CHECK_UNHANDLED_OOPS } -void JavaThread::check_for_valid_safepoint_state(bool allow_gcalot) { +void JavaThread::check_for_valid_safepoint_state() { // Don't complain if running a debugging command. if (DebuggingContext::is_enabled()) return; @@ -290,11 +290,18 @@ void JavaThread::check_for_valid_safepoint_state(bool allow_gcalot) { // are held. check_possible_safepoint(); - if (thread_state() != _thread_in_vm) { - fatal("LEAF method calling lock?"); + switch (thread_state()) { + case _thread_in_vm: + // In debug builds, leaf entries use NoHandleMark and NoSafepointVerifier (checked above). + if (handle_area()->no_handle_mark_active()) { + fatal("LEAF method calling lock?"); + } + break; + default: + fatal("illegal thread state %d, LEAF method calling lock?", thread_state()); } - if (GCALotAtAllSafepoints && allow_gcalot) { + if (GCALotAtAllSafepoints) { // We could enter a safepoint here and thus have a gc InterfaceSupport::check_gc_alot(); } @@ -1096,24 +1103,6 @@ void JavaThread::verify_not_published() { } #endif -// Slow path when the native==>Java barriers detect a safepoint/handshake is -// pending, when _suspend_flags is non-zero or when we need to process a stack -// watermark. Also check for pending async exceptions (except unsafe access error). -void JavaThread::check_special_condition_for_native_trans(JavaThread *thread) { - assert(thread->thread_state() == _thread_in_vm, "wrong state"); - assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "Unwalkable stack in native->Java transition"); - - // Enable WXWrite: called directly from interpreter native wrapper. - MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread)); - - SafepointMechanism::process_if_requested_with_exit_check(thread, true /* check asyncs */); - - // After returning from native, it could be that the stack frames are not - // yet safe to use. We catch such situations in the subsequent stack watermark - // barrier, which will trap unsafe stack frames. - StackWatermarkSet::before_unwind(thread); -} - #ifndef PRODUCT // Deoptimization // Function for testing deoptimization diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index b08a4e6da007..f3e3617a40b9 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -284,7 +284,7 @@ class JavaThread: public Thread { public: // These functions check conditions before possibly going to a safepoint. // including NoSafepointVerifier. - void check_for_valid_safepoint_state(bool allow_gcalot = true) NOT_DEBUG_RETURN; + void check_for_valid_safepoint_state() NOT_DEBUG_RETURN; void check_possible_safepoint() NOT_DEBUG_RETURN; #ifdef ASSERT @@ -666,9 +666,6 @@ class JavaThread: public Thread { bool is_suspended() { return _suspend_resume_manager.is_suspended(); } SuspendResumeManager* suspend_resume_manager() { return &_suspend_resume_manager; } - // Check for async exception in addition to safepoint. - static void check_special_condition_for_native_trans(JavaThread *thread); - // Synchronize with another thread that is deoptimizing objects of the // current thread, i.e. reverts optimizations based on escape analysis. void wait_for_object_deoptimization(); diff --git a/src/hotspot/share/runtime/javaThread.inline.hpp b/src/hotspot/share/runtime/javaThread.inline.hpp index a5a3f9990cfb..9d0870e7d930 100644 --- a/src/hotspot/share/runtime/javaThread.inline.hpp +++ b/src/hotspot/share/runtime/javaThread.inline.hpp @@ -111,10 +111,14 @@ class UnsafeAccessErrorHandshakeClosure : public AsyncHandshakeClosure { public: UnsafeAccessErrorHandshakeClosure() : AsyncHandshakeClosure("UnsafeAccessErrorHandshakeClosure") {} void do_thread(Thread* thr) { + PRAGMA_DIAG_PUSH + PRAGMA_NONNULL_IGNORED + // Suppress GCC warning for nonnull as it doesn't recognize that `thr` is always the current thread. JavaThread* self = JavaThread::cast(thr); assert(self == JavaThread::current(), "must be"); self->handshake_state()->handle_unsafe_access_error(); + PRAGMA_DIAG_POP } bool is_async_exception() { return true; } }; @@ -138,25 +142,15 @@ inline JavaThread::NoAsyncExceptionDeliveryMark::~NoAsyncExceptionDeliveryMark() } inline JavaThreadState JavaThread::thread_state() const { -#if defined(PPC64) || defined (AARCH64) || defined(RISCV64) - // Use membars when accessing volatile _thread_state. See - // Threads::create_vm() for size checks. + // Use membars when accessing volatile _thread_state. return AtomicAccess::load_acquire(&_thread_state); -#else - return AtomicAccess::load(&_thread_state); -#endif } inline void JavaThread::set_thread_state(JavaThreadState s) { assert(current_or_null() == nullptr || current_or_null() == this, "state change should only be called by the current thread"); -#if defined(PPC64) || defined (AARCH64) || defined(RISCV64) - // Use membars when accessing volatile _thread_state. See - // Threads::create_vm() for size checks. + // Use membars when accessing volatile _thread_state. AtomicAccess::release_store(&_thread_state, s); -#else - AtomicAccess::store(&_thread_state, s); -#endif } inline void JavaThread::set_thread_state_fence(JavaThreadState s) { diff --git a/src/hotspot/share/runtime/mutex.cpp b/src/hotspot/share/runtime/mutex.cpp index 9f3be83b3e0b..6627b4e4b6b8 100644 --- a/src/hotspot/share/runtime/mutex.cpp +++ b/src/hotspot/share/runtime/mutex.cpp @@ -61,7 +61,7 @@ void Mutex::check_block_state(Thread* thread) { "locking not allowed when crash protection is set"); } -void Mutex::check_safepoint_state(Thread* thread, bool allow_gcalot) { +void Mutex::check_safepoint_state(Thread* thread) { check_block_state(thread); // If the lock acquisition checks for safepoint, verify that the lock was created with rank that @@ -72,7 +72,7 @@ void Mutex::check_safepoint_state(Thread* thread, bool allow_gcalot) { if (thread->is_active_Java_thread()) { // Also check NoSafepointVerifier, and thread state is _thread_in_vm - JavaThread::cast(thread)->check_for_valid_safepoint_state(allow_gcalot); + JavaThread::cast(thread)->check_for_valid_safepoint_state(); } } @@ -116,7 +116,7 @@ void Mutex::lock_contended(Thread* self) { void Mutex::lock(Thread* self) { assert(owner() != self, "invariant"); - check_safepoint_state(self, true /* allow_gcalot */); + check_safepoint_state(self); check_rank(self); OrderAccess::fence(); @@ -246,10 +246,13 @@ bool Monitor::wait(uint64_t timeout) { // Check safepoint state after resetting owner and possible NSV. // Although the (HotSpot) monitor is logically released, the underlying - // OS monitor is still held. If this is the Heap_lock we would - // deadlock in the GC prologue trying to acquire the lock recursively. - // Suppress GC-a-lot in that case. - check_safepoint_state(self, this != Heap_lock); + // OS monitor is still held. Do not execute GC-a-lot here because + // garbage collection may (in)directly require the current monitor to + // progress. + { + SkipGCALot sgcalot(self); + check_safepoint_state(self); + } int wait_status; InFlightMutexRelease ifmr(this); diff --git a/src/hotspot/share/runtime/mutex.hpp b/src/hotspot/share/runtime/mutex.hpp index e497fbb34585..4d30a320cbf8 100644 --- a/src/hotspot/share/runtime/mutex.hpp +++ b/src/hotspot/share/runtime/mutex.hpp @@ -141,7 +141,7 @@ class Mutex : public CHeapObj { protected: void set_owner_implementation(Thread* owner) NOT_DEBUG({ raw_set_owner(owner);}); void check_block_state (Thread* thread) NOT_DEBUG_RETURN; - void check_safepoint_state (Thread* thread, bool allow_gcalot) NOT_DEBUG_RETURN; + void check_safepoint_state (Thread* thread) NOT_DEBUG_RETURN; void check_no_safepoint_state(Thread* thread) NOT_DEBUG_RETURN; void check_rank (Thread* thread) NOT_DEBUG_RETURN; void assert_owner (Thread* expected) NOT_DEBUG_RETURN; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 3c126a034484..52bbebec88d5 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -217,27 +217,10 @@ class ObjectMonitor : public CHeapObj { static ByteSize succ_offset() { return byte_offset_of(ObjectMonitor, _succ); } static ByteSize entry_list_offset() { return byte_offset_of(ObjectMonitor, _entry_list); } - // ObjectMonitor references can be ORed with markWord::monitor_value - // as part of the ObjectMonitor tagging mechanism. When we combine an - // ObjectMonitor reference with an offset, we need to remove the tag - // value in order to generate the proper address. - // - // We can either adjust the ObjectMonitor reference and then add the - // offset or we can adjust the offset that is added to the ObjectMonitor - // reference. The latter avoids an AGI (Address Generation Interlock) - // stall so the helper macro adjusts the offset value that is returned - // to the ObjectMonitor reference manipulation code: - // - #define OM_OFFSET_NO_MONITOR_VALUE_TAG(f) \ - ((in_bytes(ObjectMonitor::f ## _offset())) - checked_cast(markWord::monitor_value)) - uintptr_t metadata() const; void set_metadata(uintptr_t value); volatile uintptr_t* metadata_addr(); - markWord header() const; - void set_header(markWord hdr); - intptr_t hash() const; void set_hash(intptr_t hash); diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index 5e9d3dee5624..238c035c4b46 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -74,18 +74,6 @@ inline volatile uintptr_t* ObjectMonitor::metadata_addr() { return &_metadata; } -inline markWord ObjectMonitor::header() const { - // Locking with OM table does not use header. - ShouldNotCallThis(); - return markWord(metadata()); -} - -inline void ObjectMonitor::set_header(markWord hdr) { - // Locking with OM table does not use header. - ShouldNotCallThis(); - set_metadata(hdr.value()); -} - inline intptr_t ObjectMonitor::hash() const { return metadata(); } diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 0b79c7a4285a..9c77c5e30abf 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -2135,7 +2135,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz // goal without. In that case, we optimize probing by sorting the attach // points: We attempt outermost points first, then work ourselves up to // the middle. That reduces address space fragmentation. We also alternate - // hemispheres, which increases the chance of successfull mappings if the + // hemispheres, which increases the chance of successful mappings if the // previous mapping had been blocked by large maps. hemi_split(points, num_attempts); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index aaf9c956ca07..e00dd3213e19 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -2099,14 +2099,6 @@ void SharedRuntime::monitor_exit_helper(oopDesc* obj, BasicLock* lock, JavaThrea } } - // 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()) { - if (CheckJNICalls) { - fatal("Object has been unlocked by JNI"); - } - return; - } ObjectSynchronizer::exit(obj, lock, current); } @@ -3336,13 +3328,17 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterHandlerEntry* handler, allocate_code_blob); if (ces.has_scalarized_args()) { - // Save a C heap allocated version of the scalarized signature and store it in the adapter - GrowableArray* heap_sig = new (mtCode) GrowableArray(ces.sig_cc()->length(), mtCode); - heap_sig->appendAll(ces.sig_cc()); - handler->set_sig_cc(heap_sig); - heap_sig = new (mtCode) GrowableArray(ces.sig_cc_ro()->length(), mtCode); - heap_sig->appendAll(ces.sig_cc_ro()); - handler->set_sig_cc_ro(heap_sig); + assert((handler->get_sig_cc() == nullptr) == (handler->get_sig_cc_ro() == nullptr), "Inconsistency"); + // Check if scalarized signatures have to be initialized + if (handler->get_sig_cc() == nullptr) { + // Save a C heap allocated version of the scalarized signature and store it in the adapter + GrowableArray* heap_sig = new (mtCode) GrowableArray(ces.sig_cc()->length(), mtCode); + heap_sig->appendAll(ces.sig_cc()); + handler->set_sig_cc(heap_sig); + heap_sig = new (mtCode) GrowableArray(ces.sig_cc_ro()->length(), mtCode); + heap_sig->appendAll(ces.sig_cc_ro()); + handler->set_sig_cc_ro(heap_sig); + } } // On zero there is no code to save and no need to create a blob and // or relocate the handler. @@ -4215,3 +4211,24 @@ JRT_BLOCK_ENTRY(void, SharedRuntime::store_inline_type_fields_to_buf(JavaThread* JRT_BLOCK_END; } JRT_END + +// Slow path when the native==>Java barriers detect a safepoint/handshake is +// pending, when _suspend_flags is non-zero or when we need to process a stack +// watermark. Also check for pending async exceptions (except unsafe access error). +JRT_BLOCK_ENTRY(void, SharedRuntime::check_special_condition_for_native_trans(JavaThread *current)) + assert(!current->has_last_Java_frame() || current->frame_anchor()->walkable(), "Unwalkable stack in native->Java transition"); + + JRT_BLOCK + // This block looks empty, but the ThreadInVMfromJava hidden in the macro + // does all the heavy lifting. + + // On block exit, process safepoint, check for pending async exceptions, etc + JRT_BLOCK_END + + // After returning from native, it could be that the stack frames are not + // yet safe to use. We catch such situations in the subsequent stack watermark + // barrier, which will trap unsafe stack frames. + // This must happen after processing the safepoint, otherwise preconditions for + // before_unwind are not met. + StackWatermarkSet::before_unwind(current); +JRT_END diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 5accc54a629e..c0139870df90 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -690,6 +690,10 @@ class SharedRuntime: AllStatic { #endif // PRODUCT static void print_statistics() PRODUCT_RETURN; + + // native --> Java safepoint entry point + // Check for async exception in addition to safepoint. + static void check_special_condition_for_native_trans(JavaThread *current); }; diff --git a/src/hotspot/share/runtime/stackValue.cpp b/src/hotspot/share/runtime/stackValue.cpp index 8b613ff72801..fb91eb7e4c83 100644 --- a/src/hotspot/share/runtime/stackValue.cpp +++ b/src/hotspot/share/runtime/stackValue.cpp @@ -77,7 +77,7 @@ static oop oop_from_oop_location(stackChunkOop chunk, void* addr) { // stack values. Note: do not heal the location, to avoid accidentally // corrupting the stack. Stack watermark barriers are supposed to handle // the healing. - val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(val); + val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, val, (oop*)nullptr); } #endif @@ -114,7 +114,7 @@ static oop oop_from_narrowOop_location(stackChunkOop chunk, void* addr, bool is_ // stack values. Note: do not heal the location, to avoid accidentally // corrupting the stack. Stack watermark barriers are supposed to handle // the healing. - val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(val); + val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_STRONG_OOP_REF, val, (narrowOop*)nullptr); } #endif diff --git a/src/hotspot/share/runtime/stubCodeGenerator.cpp b/src/hotspot/share/runtime/stubCodeGenerator.cpp index 252f90e1bde3..7f5c2286faea 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.cpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -291,7 +291,7 @@ StubCodeMark::StubCodeMark(StubCodeGenerator* cgen, StubId stub_id) : StubCodeMa } StubCodeMark::~StubCodeMark() { - _cgen->assembler()->flush(); + _cgen->assembler()->invalidate_icache(); _cdesc->set_end(_cgen->assembler()->pc()); assert(StubCodeDesc::_list == _cdesc, "expected order on list"); #ifndef PRODUCT diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index fb2f8bd43033..da60b586b8df 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -373,7 +373,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al } if (mark.has_monitor()) { - ObjectMonitor* const mon = read_monitor(obj, mark); + ObjectMonitor* const mon = read_monitor(obj); if (mon == nullptr) { // Racing with inflation/deflation go slow path return false; @@ -635,7 +635,7 @@ static SharedGlobals GVars; // There are simple ways to "diffuse" the middle address bits over the // generated hashCode values: -static intptr_t get_next_hash(Thread* current, oop obj) { +intptr_t ObjectSynchronizer::get_next_hash(Thread* current, oop obj) { intptr_t value = 0; if (hashCode == 0) { // This form uses global Park-Miller RNG. @@ -675,30 +675,6 @@ static intptr_t get_next_hash(Thread* current, oop obj) { return value; } -intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { - // VM should be calling bootstrap method. - assert(!obj->klass()->is_inline_klass(), "FastHashCode should not be called for inline classes"); - - while (true) { - markWord temp, test; - intptr_t hash; - markWord mark = obj->mark_acquire(); - // The hash is located in the object header. - hash = mark.hash(); - if (hash != 0) { // if it has a hash, just return it - return hash; - } - hash = get_next_hash(current, obj); // get a new hash - temp = mark.copy_set_hash(hash); // merge the hash into header - // try to install the hash - test = obj->cas_set_mark(temp, mark); - if (test == mark) { // if the hash was installed, return it - return hash; - } - // CAS failed, retry - } -} - bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, Handle h_obj) { if (h_obj->mark().is_inline_type()) { @@ -715,7 +691,7 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, } while (mark.has_monitor()) { - ObjectMonitor* monitor = read_monitor(obj, mark); + ObjectMonitor* monitor = read_monitor(obj); if (monitor != nullptr) { return monitor->is_entered(current) != 0; } @@ -728,8 +704,8 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, } } - // Unlocked case, header in place - assert(mark.is_unlocked(), "sanity check"); + // Lock-neutral case + assert(mark.is_lock_neutral(), "sanity check"); return false; } @@ -744,7 +720,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob } while (mark.has_monitor()) { - ObjectMonitor* monitor = read_monitor(obj, mark); + ObjectMonitor* monitor = read_monitor(obj); if (monitor != nullptr) { return Threads::owning_thread_from_monitor(t_list, monitor); } @@ -752,16 +728,12 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob mark = obj->mark_acquire(); if (mark.is_fast_locked()) { - // Some other thread fast_locked + // Some other thread fast-locked the object. return Threads::owning_thread_from_object(t_list, h_obj()); } } - // Unlocked case, header in place - // Cannot have assertion since this object may have been - // locked by another thread when reaching here. - // assert(mark.is_unlocked(), "sanity check"); - + // Lock-neutral case return nullptr; } @@ -1377,7 +1349,7 @@ void ObjectSynchronizer::chk_in_use_entry(ObjectMonitor* n, outputStream* out, } const markWord mark = obj->mark(); - ObjectMonitor* const obj_mon = read_monitor(obj, mark); + ObjectMonitor* const obj_mon = read_monitor(obj); if (n != obj_mon) { out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use monitor's " "object does not refer to the same monitor: obj=" @@ -1506,10 +1478,10 @@ void ObjectSynchronizer::remove_monitor(ObjectMonitor* monitor, oop obj) { void ObjectSynchronizer::deflate_mark_word(oop obj) { markWord mark = obj->mark_acquire(); - assert(!mark.has_no_hash(), "obj with inflated monitor must have had a hash"); + assert(mark.has_hash(), "obj with inflated monitor must have had a hash"); while (mark.has_monitor()) { - const markWord new_mark = mark.clear_lock_bits().set_unlocked(); + const markWord new_mark = mark.set_lock_neutral(); mark = obj->cas_set_mark(new_mark, mark); } } @@ -1631,14 +1603,14 @@ class ObjectSynchronizer::VerifyThreadState { inline bool ObjectSynchronizer::fast_lock_try_enter(oop obj, LockStack& lock_stack, JavaThread* current) { markWord mark = obj->mark(); - while (mark.is_unlocked()) { + while (mark.is_lock_neutral()) { ensure_lock_stack_space(current); assert(!lock_stack.is_full(), "must have made room on the lock stack"); assert(!lock_stack.contains(obj), "thread must not already hold the lock"); // Try to swing into 'fast-locked' state. - markWord locked_mark = mark.set_fast_locked(); + markWord fast_locked_mark = mark.set_fast_locked(); markWord old_mark = mark; - mark = obj->cas_set_mark(locked_mark, old_mark); + mark = obj->cas_set_mark(fast_locked_mark, old_mark); if (old_mark == mark) { // Successfully fast-locked, push object to lock-stack and return. lock_stack.push(obj); @@ -1660,7 +1632,7 @@ bool ObjectSynchronizer::fast_lock_spin_enter(oop obj, LockStack& lock_stack, Ja return true; } else if (observed_deflation) { // Spin while monitor is being deflated. - ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark); + ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj); return monitor == nullptr || monitor->is_being_async_deflated(); } // Else stop spinning. @@ -1786,7 +1758,6 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) assert(current == Thread::current(), "must be"); markWord mark = object->mark(); - assert(!mark.is_unlocked(), "must be"); LockStack& lock_stack = current->lock_stack(); if (mark.is_fast_locked()) { @@ -1803,9 +1774,9 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) } while (mark.is_fast_locked()) { - markWord unlocked_mark = mark.set_unlocked(); + markWord lock_neutral_mark = mark.set_lock_neutral(); markWord old_mark = mark; - mark = object->cas_set_mark(unlocked_mark, old_mark); + mark = object->cas_set_mark(lock_neutral_mark, old_mark); if (old_mark == mark) { // CAS successful, remove from lock_stack size_t recursion = lock_stack.remove(object) - 1; @@ -1814,6 +1785,16 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) } } + // 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 (mark.is_lock_neutral()) { + if (CheckJNICalls) { + fatal("Object has been unlocked by JNI"); + } + + return; + } + assert(mark.has_monitor(), "must be"); // The monitor exists ObjectMonitor* monitor; @@ -1842,7 +1823,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_locked_or_imse(oop obj, ObjectSynchro for (;;) { markWord mark = obj->mark_acquire(); - if (mark.is_unlocked()) { + if (mark.is_lock_neutral()) { // No lock, IMSE. THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread is not owner", nullptr); @@ -1860,7 +1841,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_locked_or_imse(oop obj, ObjectSynchro } assert(mark.has_monitor(), "must be"); - ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark); + ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj); if (monitor != nullptr) { if (monitor->has_anonymous_owner()) { LockStack& lock_stack = current->lock_stack(); @@ -1887,10 +1868,10 @@ ObjectMonitor* ObjectSynchronizer::inflate_fast_locked_object(oop object, Object ObjectMonitor* monitor; // Inflating requires a hash code - ObjectSynchronizer::FastHashCode(current, object); + (void)object->identity_hash(current); markWord mark = object->mark_acquire(); - assert(!mark.is_unlocked(), "Cannot be unlocked"); + assert(mark.is_fast_locked() || mark.has_monitor(), "Must be fast-locked or async inflated"); for (;;) { // Fetch the monitor from the table @@ -1952,7 +1933,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock // Get or create the monitor if (monitor == nullptr) { // Lightweight monitors require that hash codes are installed first - ObjectSynchronizer::FastHashCode(locking_thread, object); + (void)object->identity_hash(locking_thread); monitor = get_or_insert_monitor(object, current, cause); } @@ -1984,7 +1965,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock os::naked_yield(); } else { - assert(mark.is_unlocked(), "Implied"); + assert(mark.is_lock_neutral(), "Implied"); // Retry immediately } @@ -2001,7 +1982,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock // the ObjectMonitor owner and remove the // lock from the locking_thread's lock stack. // * fast-locked - Coerce it to inflated from fast-locked. - // * neutral - Inflate the object. Successful CAS is locked + // * lock-neutral - Inflate the object. Successful CAS is locked // CASE: inflated if (mark.has_monitor()) { @@ -2038,18 +2019,16 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock break; // Success } - // CASE: neutral (unlocked) + // CASE: lock-neutral - // Catch if the object's header is not neutral (not locked and - // not marked is what we care about here). - assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); + assert(mark.is_lock_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); markWord old_mark = object->cas_set_mark(mark.set_has_monitor(), mark); if (old_mark != mark) { // CAS failed continue; } - // Transitioned from unlocked to monitor means locking_thread owns the lock. + // Transitioned from lock-neutral to monitor means locking_thread owns the lock. monitor->set_owner_from_anonymous(locking_thread); return monitor; @@ -2090,10 +2069,6 @@ ObjectMonitor* ObjectSynchronizer::get_monitor_from_table(oop obj) { } ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj) { - return ObjectSynchronizer::read_monitor(obj, obj->mark()); -} - -ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj, markWord mark) { return ObjectSynchronizer::get_monitor_from_table(obj); } @@ -2117,9 +2092,9 @@ bool ObjectSynchronizer::quick_enter_internal(oop obj, BasicLock* lock, JavaThre return true; } - if (mark.is_unlocked()) { - markWord locked_mark = mark.set_fast_locked(); - if (obj->cas_set_mark(locked_mark, mark) == mark) { + if (mark.is_lock_neutral()) { + markWord fast_locked_mark = mark.set_fast_locked(); + if (obj->cas_set_mark(fast_locked_mark, mark) == mark) { // Successfully fast-locked, push object to lock-stack and return. lock_stack.push(obj); return true; diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index 922d988e290a..adbb86eb859e 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -126,11 +126,8 @@ class ObjectSynchronizer : AllStatic { static const char* inflate_cause_name(const InflateCause cause); static ObjectMonitor* read_monitor(oop obj); - static ObjectMonitor* read_monitor(oop obj, markWord mark); - // Returns the identity hash value for an oop - // NOTE: It may cause monitor inflation - static intptr_t FastHashCode(Thread* current, oop obj); + static intptr_t get_next_hash(Thread* current, oop obj); // java.lang.Thread support static bool current_thread_holds_lock(JavaThread* current, Handle h_obj); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 8ebedb79bfc6..5b0f53f2189c 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -667,4 +667,28 @@ inline Thread* Thread::current_or_null_safe() { return nullptr; } +// A SkipGCALot object is used to elide the usual effect of gc-a-lot +// over a section of execution by a thread. +class SkipGCALot : public StackObj { + private: + bool _saved; + Thread* _t; + + public: +#ifdef ASSERT + SkipGCALot(Thread* t) : _t(t) { + _saved = _t->skip_gcalot(); + _t->set_skip_gcalot(true); + } + + ~SkipGCALot() { + assert(_t->skip_gcalot(), "Save-restore protocol invariant"); + _t->set_skip_gcalot(_saved); + } +#else + SkipGCALot(Thread* t) { } + ~SkipGCALot() { } +#endif +}; + #endif // SHARE_RUNTIME_THREAD_HPP diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 6663966f36e0..1000a7563dfd 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -667,7 +667,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // is initially computed. See Abstract_VM_Version::vm_info_string(). // This update must happen before we initialize the java classes, but // after any initialization logic that might modify the flags. - Arguments::update_vm_info_property(VM_Version::vm_info_string()); + const char* vm_info_str = VM_Version::vm_info_string(); + Arguments::update_vm_info_property(vm_info_str); + FREE_C_HEAP_ARRAY(vm_info_str); JavaThread* THREAD = JavaThread::current(); // For exception macros. HandleMark hm(THREAD); @@ -1327,10 +1329,14 @@ void Threads::print_on(outputStream* st, bool print_stacks, char buf[32]; st->print_raw_cr(os::local_time_string(buf, sizeof(buf))); + const char* vm_info_str = VM_Version::vm_info_string(); st->print_cr("Full thread dump %s (%s %s)", VM_Version::vm_name(), VM_Version::vm_release(), - VM_Version::vm_info_string()); + vm_info_str); + FREE_C_HEAP_ARRAY(vm_info_str); + + JDK_Version::current().to_string(buf, sizeof(buf)); const char* runtime_name = JDK_Version::runtime_name() != nullptr ? JDK_Version::runtime_name() : ""; diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index b5243fd03b32..e0a3ffbcf510 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -248,7 +248,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, bool is_virtual, int frame // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. if (mark.has_monitor()) { - ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark); + ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner()); if (// if the monitor is null we must be in the process of locking mon == nullptr || // we have marked ourself as pending on this monitor diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index 050bfee131b0..66af4db24aab 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -93,7 +93,6 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { dest->set_obj(nullptr); } else { assert(monitor->owner() != nullptr, "monitor owner must not be null"); - assert(!monitor->owner()->is_unlocked(), "monitor must be locked"); dest->set_obj(monitor->owner()); assert(ObjectSynchronizer::current_thread_holds_lock(current_thread, Handle(current_thread, dest->obj())), "should be held, before move_to"); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 3196b6f31ef3..789699368823 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1815,8 +1815,8 @@ declare_constant(markWord::hash_mask) \ declare_constant(markWord::hash_mask_in_place) \ \ - declare_constant(markWord::locked_value) \ - declare_constant(markWord::unlocked_value) \ + declare_constant(markWord::fast_locked_value) \ + declare_constant(markWord::lock_neutral_value) \ declare_constant(markWord::monitor_value) \ declare_constant(markWord::marked_value) \ \ diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index 260b0f6f0433..505b53f5909f 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -488,31 +488,6 @@ void VMThread::loop() { } } -// A SkipGCALot object is used to elide the usual effect of gc-a-lot -// over a section of execution by a thread. Currently, it's used only to -// prevent re-entrant calls to GC. -class SkipGCALot : public StackObj { - private: - bool _saved; - Thread* _t; - - public: -#ifdef ASSERT - SkipGCALot(Thread* t) : _t(t) { - _saved = _t->skip_gcalot(); - _t->set_skip_gcalot(true); - } - - ~SkipGCALot() { - assert(_t->skip_gcalot(), "Save-restore protocol invariant"); - _t->set_skip_gcalot(_saved); - } -#else - SkipGCALot(Thread* t) { } - ~SkipGCALot() { } -#endif -}; - void VMThread::execute(VM_Operation* op) { Thread* t = Thread::current(); diff --git a/src/hotspot/share/services/finalizerService.cpp b/src/hotspot/share/services/finalizerService.cpp index d57d0fb5b50c..6d78ca1e9786 100644 --- a/src/hotspot/share/services/finalizerService.cpp +++ b/src/hotspot/share/services/finalizerService.cpp @@ -299,7 +299,7 @@ static FinalizerEntry* get_entry(oop finalizee, Thread* thread) { static void log_registered(oop finalizee, Thread* thread) { ResourceMark rm(thread); - const intptr_t identity_hash = ObjectSynchronizer::FastHashCode(thread, finalizee); + const intptr_t identity_hash = finalizee->identity_hash(thread); log_info(finalizer)("Registered object (" INTPTR_FORMAT ") of class %s as finalizable", identity_hash, finalizee->klass()->external_name()); } @@ -314,7 +314,7 @@ void FinalizerService::on_register(oop finalizee, Thread* thread) { static void log_completed(oop finalizee, Thread* thread) { ResourceMark rm(thread); - const intptr_t identity_hash = ObjectSynchronizer::FastHashCode(thread, finalizee); + const intptr_t identity_hash = finalizee->identity_hash(thread); log_info(finalizer)("Finalizer was run for object (" INTPTR_FORMAT ") of class %s", identity_hash, finalizee->klass()->external_name()); } diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index 6e18732284b3..37a672556a29 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -1258,7 +1258,7 @@ class GetThreadSnapshotHandshakeClosure: public HandshakeClosure { // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. if (mark.has_monitor()) { - ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark); + ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner()); if (// if the monitor is null we must be in the process of locking mon == nullptr || // we have marked ourself as pending on this monitor diff --git a/src/hotspot/share/utilities/bytes.hpp b/src/hotspot/share/utilities/bytes.hpp index 99f3c9749bf7..03c0a6566d41 100644 --- a/src/hotspot/share/utilities/bytes.hpp +++ b/src/hotspot/share/utilities/bytes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,10 @@ #ifndef SHARE_UTILITIES_BYTES_HPP #define SHARE_UTILITIES_BYTES_HPP -#include "utilities/macros.hpp" +#include "memory/allStatic.hpp" +#include "utilities/byteswap.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/unalignedAccess.hpp" class Endian : AllStatic { public: @@ -48,6 +51,55 @@ class Endian : AllStatic { } }; -#include CPU_HEADER(bytes) +class Bytes : AllStatic { + public: + // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering. + template + static inline T get_native(const void* p) { + return UnalignedAccess::load(p); + } + + template + static inline void put_native(void* p, T x) { + UnalignedAccess::store(p, x); + } + + static inline u2 get_native_u2(address p) { return get_native(p); } + static inline u4 get_native_u4(address p) { return get_native(p); } + static inline u8 get_native_u8(address p) { return get_native(p); } + static inline void put_native_u2(address p, u2 x) { put_native(p, x); } + static inline void put_native_u4(address p, u4 x) { put_native(p, x); } + static inline void put_native_u8(address p, u8 x) { put_native(p, x); } + + // Efficient reading and writing of unaligned unsigned data in Java + // byte ordering (i.e. big-endian ordering). + template + static inline T get_Java(const address p) { + T x = get_native(p); + + if (Endian::is_Java_byte_ordering_different()) { + x = byteswap(x); + } + + return x; + } + + template + static inline void put_Java(address p, T x) { + if (Endian::is_Java_byte_ordering_different()) { + x = byteswap(x); + } + + put_native(p, x); + } + + static inline u2 get_Java_u2(address p) { return get_Java(p); } + static inline u4 get_Java_u4(address p) { return get_Java(p); } + static inline u8 get_Java_u8(address p) { return get_Java(p); } + + static inline void put_Java_u2(address p, u2 x) { put_Java(p, x); } + static inline void put_Java_u4(address p, u4 x) { put_Java(p, x); } + static inline void put_Java_u8(address p, u8 x) { put_Java(p, x); } +}; #endif // SHARE_UTILITIES_BYTES_HPP diff --git a/src/hotspot/share/utilities/unalignedAccess.hpp b/src/hotspot/share/utilities/unalignedAccess.hpp new file mode 100644 index 000000000000..dd18381e9275 --- /dev/null +++ b/src/hotspot/share/utilities/unalignedAccess.hpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 Google and/or its affiliates. All rights reserved. + * 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_UNALIGNED_ACCESS_HPP +#define SHARE_UTILITIES_UNALIGNED_ACCESS_HPP + +#include "memory/allStatic.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" + +#ifdef ADDRESS_SANITIZER +// ASan, HWAsan, MSan, and TSan have special support for unaligned access. +// If we ever support the others, update the above ifdef. +#define SANITIZER_HAS_UNALIGNED_ACCESS 1 +#endif + +#ifdef SANITIZER_HAS_UNALIGNED_ACCESS +#include +#endif + +#include +#include +#include + +// Provides access to unaligned data. +class UnalignedAccess : AllStatic { + public: + template + static void store(void* ptr, T value) { + static_assert(std::is_trivially_copyable::value); + assert(ptr != nullptr, "nullptr"); + StoreImpl{}(static_cast(ptr), value); + } + + template + static T load(const void* ptr) { + static_assert(std::is_trivially_copyable::value); + assert(ptr != nullptr, "nullptr"); + return LoadImpl{}(static_cast(ptr)); + } + + private: + template struct StoreImpl; + template struct LoadImpl; +}; + +template<> +struct UnalignedAccess::StoreImpl<1> { + template + void operator()(T* ptr, T value) const { + static_assert(sizeof(T) == sizeof(uint8_t)); + *ptr = value; + } +}; + +template<> +struct UnalignedAccess::LoadImpl<1> { + template + T operator()(const T* ptr) const { + static_assert(sizeof(T) == sizeof(uint8_t)); + return *ptr; + } +}; + +#ifdef SANITIZER_HAS_UNALIGNED_ACCESS +template<> +struct UnalignedAccess::StoreImpl<2> { + template + void operator()(T* ptr, T value) const { + static_assert(sizeof(T) == sizeof(uint16_t)); + __sanitizer_unaligned_store16(ptr, static_cast(value)); + } +}; + +template<> +struct UnalignedAccess::StoreImpl<4> { + template + void operator()(T* ptr, T value) const { + static_assert(sizeof(T) == sizeof(uint32_t)); + __sanitizer_unaligned_store32(ptr, static_cast(value)); + } +}; + +template<> +struct UnalignedAccess::StoreImpl<8> { + template + void operator()(T* ptr, T value) const { + static_assert(sizeof(T) == sizeof(uint64_t)); + __sanitizer_unaligned_store64(ptr, static_cast(value)); + } +}; + +template<> +struct UnalignedAccess::LoadImpl<2> { + template + T operator()(const T* ptr) const { + static_assert(sizeof(T) == sizeof(uint16_t)); + return static_cast(__sanitizer_unaligned_load16(ptr)); + } +}; + +template<> +struct UnalignedAccess::LoadImpl<4> { + template + T operator()(const T* ptr) const { + static_assert(sizeof(T) == sizeof(uint32_t)); + return static_cast(__sanitizer_unaligned_load32(ptr)); + } +}; + +template<> +struct UnalignedAccess::LoadImpl<8> { + template + T operator()(const T* ptr) const { + static_assert(sizeof(T) == sizeof(uint64_t)); + return static_cast(__sanitizer_unaligned_load64(ptr)); + } +}; +#else +template +struct UnalignedAccess::StoreImpl { + template + void operator()(T* ptr, T value) const { + static_assert(sizeof(T) == byte_size); + static_assert(byte_size != 0); // Incomplete type + // The only portable way to implement unaligned stores is to use memcpy. + // Fortunately all decent compilers are able to inline this and avoid + // the actual call to memcpy. On platforms which allow unaligned access, + // the compiler will emit a normal store instruction. + memcpy(ptr, &value, sizeof(T)); + } +}; + +template +struct UnalignedAccess::LoadImpl { + template + T operator()(const T* ptr) const { + static_assert(sizeof(T) == byte_size); + static_assert(byte_size != 0); // Incomplete type + // The only portable way to implement unaligned loads is to use memcpy. + // Fortunately all decent compilers are able to inline this and avoid + // the actual call to memcpy. On platforms which allow unaligned access, + // the compiler will emit a normal load instruction. + T value; + memcpy(&value, ptr, sizeof(T)); + return value; + } +}; +#endif // SANITIZER_HAS_UNALIGNED_ACCESS + +#undef SANITIZER_HAS_UNALIGNED_ACCESS + +#endif // SHARE_UTILITIES_UNALIGNED_ACCESS_HPP diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 045fcc23d631..6fb2cb96a029 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -516,18 +516,20 @@ static void report_vm_version(outputStream* st, char* buf, int buflen) { buf, jdk_debug_level, runtime_version); // This is the long version with some default settings added + const char* vm_info_str = VM_Version::vm_info_string(); st->print_cr("# Java VM: %s%s%s (%s%s, %s%s%s%s, %s, %s)", VM_Version::vm_name(), (*vendor_version != '\0') ? " " : "", vendor_version, jdk_debug_level, VM_Version::vm_release(), - VM_Version::vm_info_string(), + vm_info_str, TieredCompilation ? ", tiered" : "", UseCompressedOops ? ", compressed oops" : "", UseCompactObjectHeaders ? ", compact obj headers" : "", GCConfig::hs_err_name(), VM_Version::vm_platform_string() ); + FREE_C_HEAP_ARRAY(vm_info_str); } // Returns true if at least one thread reported a fatal error and fatal error handling is in process. @@ -540,15 +542,11 @@ bool VMError::is_error_reported_in_current_thread() { return _first_error_tid.load_relaxed() == os::current_thread_id(); } -// Helper, return current timestamp for timeout handling. -jlong VMError::get_current_timestamp() { - return os::javaTimeNanos(); -} // Factor to translate the timestamp to seconds. -#define TIMESTAMP_TO_SECONDS_FACTOR (1000 * 1000 * 1000) +#define SECONDS_TO_NANOS_FACTOR (1000 * 1000 * 1000) void VMError::record_reporting_start_time() { - const jlong now = get_current_timestamp(); + const jlong now = os::javaTimeNanos(); _reporting_start_time.store_relaxed(now); } @@ -557,7 +555,7 @@ jlong VMError::get_reporting_start_time() { } void VMError::record_step_start_time() { - const jlong now = get_current_timestamp(); + const jlong now = os::javaTimeNanos(); _step_start_time.store_relaxed(now); } @@ -1786,15 +1784,13 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt // The current step had a timeout. Lets continue reporting with the next step. st->print_raw("[timeout occurred during error reporting in step \""); st->print_raw(_current_step_info); - st->print_cr("\"] after " INT64_FORMAT " s.", - (int64_t) - ((get_current_timestamp() - get_step_start_time()) / TIMESTAMP_TO_SECONDS_FACTOR)); + st->print_cr("\"] after " JLONG_FORMAT " s.", + ((os::javaTimeNanos() - get_step_start_time()) / SECONDS_TO_NANOS_FACTOR)); } else if (_reporting_did_timeout.load_relaxed()) { // We hit ErrorLogTimeout. Reporting will stop altogether. Let's wrap things // up, the process is about to be stopped by the WatcherThread. - st->print_cr("------ Timeout during error reporting after " INT64_FORMAT " s. ------", - (int64_t) - ((get_current_timestamp() - get_reporting_start_time()) / TIMESTAMP_TO_SECONDS_FACTOR)); + st->print_cr("------ Timeout during error reporting after " JLONG_FORMAT " s. ------", + ((os::javaTimeNanos() - get_reporting_start_time()) / SECONDS_TO_NANOS_FACTOR)); st->flush(); // Watcherthread is about to call os::die. Lets just wait. os::infinite_sleep(); @@ -2079,14 +2075,14 @@ bool VMError::check_timeout() { || (OnError != nullptr && OnError[0] != '\0') || Arguments::abort_hook() != nullptr); - const jlong now = get_current_timestamp(); + const jlong now = os::javaTimeNanos(); // Global timeout hit? if (!ignore_global_timeout) { const jlong reporting_start_time = get_reporting_start_time(); // Timestamp is stored in nanos. if (reporting_start_time > 0) { - const jlong end = reporting_start_time + (jlong)ErrorLogTimeout * TIMESTAMP_TO_SECONDS_FACTOR; + const jlong end = reporting_start_time + (jlong)ErrorLogTimeout * SECONDS_TO_NANOS_FACTOR; if (end <= now && !_reporting_did_timeout.load_relaxed()) { // We hit ErrorLogTimeout and we haven't interrupted the reporting // thread yet. @@ -2100,11 +2096,14 @@ bool VMError::check_timeout() { // Reporting step timeout? const jlong step_start_time = get_step_start_time(); if (step_start_time > 0) { - // A step times out after a quarter of the total timeout. Steps are mostly fast unless they - // hang for some reason, so this simple rule allows for three hanging step and still - // hopefully leaves time enough for the rest of the steps to finish. - const int max_step_timeout_secs = 5; - const jlong timeout_duration = MAX2((jlong)max_step_timeout_secs, (jlong)ErrorLogTimeout * TIMESTAMP_TO_SECONDS_FACTOR / 4); + // Steps are very fast. If they are not fast, they typically hang without recovering. There are a few + // exceptions to this (printing a callstack from debug information located on a slow file system, or + // printing a memory map of an extremely fragmented process). To give those rare slow steps enough + // breathing space while still allowing us to skip any hanging steps, we use a per-step timeout of + // /4, or 5 seconds, whichever is smaller. + const jlong step_timeout_nanos = ((jlong)ErrorLogTimeout * SECONDS_TO_NANOS_FACTOR) / 4; + const jlong max_step_timeout_nanos = 5LL * SECONDS_TO_NANOS_FACTOR; + const jlong timeout_duration = MIN2(max_step_timeout_nanos, step_timeout_nanos); const jlong end = step_start_time + timeout_duration; if (end <= now && !_step_did_timeout.load_relaxed()) { // The step timed out and we haven't interrupted the reporting diff --git a/src/hotspot/share/utilities/vmError.hpp b/src/hotspot/share/utilities/vmError.hpp index b46ba2087884..f5c78ee7f8aa 100644 --- a/src/hotspot/share/utilities/vmError.hpp +++ b/src/hotspot/share/utilities/vmError.hpp @@ -133,9 +133,6 @@ class VMError : public AllStatic { static void reporting_started(); static void interrupt_reporting_thread(); - // Helper function to get the current timestamp. - static jlong get_current_timestamp(); - // Accessors to get/set the start times for step and total timeout. static void record_reporting_start_time(); static jlong get_reporting_start_time(); diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index 7236c3512026..3c446dc52a2e 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -533,6 +533,9 @@ final class VarHandle$InputType$s { #if[Object] @ForceInline static Object checkCast(FieldStaticReadWrite handle, $type$ value) { + if (handle.nullRestricted && value == null) { + throw new NullPointerException(); + } return handle.fieldType.cast(value); } #end[Object] diff --git a/src/java.base/share/classes/java/lang/runtime/Carriers.java b/src/java.base/share/classes/java/lang/runtime/Carriers.java deleted file mode 100644 index a74144fcbebd..000000000000 --- a/src/java.base/share/classes/java/lang/runtime/Carriers.java +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.runtime; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.invoke.MethodType; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -import jdk.internal.misc.Unsafe; -import jdk.internal.util.ReferencedKeyMap; - -import static java.lang.invoke.MethodType.methodType; - -/** - * A carrier is an opaque object that can be used to store component values - * while avoiding primitive boxing associated with collection objects. Component values - * can be primitive or Object. - *

- * Clients can create new carrier instances by describing a carrier shape, that - * is, a {@linkplain MethodType method type} whose parameter types describe the types of - * the carrier component values, or by providing the parameter types directly. - * - * {@snippet : - * // Create a carrier for a string and an integer - * CarrierElements elements = CarrierFactory.of(String.class, int.class); - * // Fetch the carrier constructor MethodHandle - * MethodHandle initializingConstructor = elements.initializingConstructor(); - * // Fetch the list of carrier component MethodHandles - * List components = elements.components(); - * - * // Create an instance of the carrier with a string and an integer - * Object carrier = initializingConstructor.invokeExact("abc", 10); - * // Extract the first component, type string - * String string = (String)components.get(0).invokeExact(carrier); - * // Extract the second component, type int - * int i = (int)components.get(1).invokeExact(carrier); - * } - * - * Alternatively, the client can use static methods when the carrier use is scattered. - * This is possible since {@link Carriers} ensures that the same underlying carrier - * class is used when the same component types are provided. - * - * {@snippet : - * // Describe carrier using a MethodType - * MethodType mt = MethodType.methodType(Object.class, String.class, int.class); - * // Fetch the carrier constructor MethodHandle - * MethodHandle constructor = Carriers.constructor(mt); - * // Fetch the list of carrier component MethodHandles - * List components = Carriers.components(mt); - * } - * - * @implNote The strategy for storing components is deliberately left unspecified - * so that future improvements will not be hampered by issues of backward compatibility. - * - * @since 21 - * - * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES. - * Do not rely on its availability. - */ -final class Carriers { - /** - * Maximum number of components in a carrier (based on the maximum - * number of args to a constructor.) - */ - public static final int MAX_COMPONENTS = 255 - /* this */ 1; - - /** - * Number of integer slots used by a long. - */ - static final int LONG_SLOTS = Long.SIZE / Integer.SIZE; - - /* - * Initialize {@link MethodHandle} constants. - */ - static { - try { - Lookup lookup = MethodHandles.lookup(); - FLOAT_TO_INT = lookup.findStatic(Float.class, "floatToRawIntBits", - methodType(int.class, float.class)); - INT_TO_FLOAT = lookup.findStatic(Float.class, "intBitsToFloat", - methodType(float.class, int.class)); - DOUBLE_TO_LONG = lookup.findStatic(Double.class, "doubleToRawLongBits", - methodType(long.class, double.class)); - LONG_TO_DOUBLE = lookup.findStatic(Double.class, "longBitsToDouble", - methodType(double.class, long.class)); - } catch (ReflectiveOperationException ex) { - throw new AssertionError("carrier static init fail", ex); - } - } - - /* - * float/double conversions. - */ - private static final MethodHandle FLOAT_TO_INT; - private static final MethodHandle INT_TO_FLOAT; - private static final MethodHandle DOUBLE_TO_LONG; - private static final MethodHandle LONG_TO_DOUBLE; - - /** - * Given an initializer {@link MethodHandle} recast and reorder arguments to - * match shape. - * - * @param carrierShape carrier shape - * @param initializer carrier constructor to reshape - * - * @return constructor with arguments recasted and reordered - */ - static MethodHandle reshapeInitializer(CarrierShape carrierShape, - MethodHandle initializer) { - int count = carrierShape.count(); - Class[] ptypes = carrierShape.ptypes(); - int objectIndex = carrierShape.objectOffset() + 1; - int intIndex = carrierShape.intOffset() + 1; - int longIndex = carrierShape.longOffset() + 1; - int[] reorder = new int[count + 1]; - Class[] permutePTypes = new Class[count + 1]; - MethodHandle[] filters = new MethodHandle[count + 1]; - boolean hasFilters = false; - permutePTypes[0] = CarrierObject.class; - reorder[0] = 0; - int index = 1; - - for (Class ptype : ptypes) { - MethodHandle filter = null; - int from; - - if (!ptype.isPrimitive()) { - from = objectIndex++; - ptype = Object.class; - } else if (ptype == double.class) { - from = longIndex++; - filter = DOUBLE_TO_LONG; - } else if (ptype == float.class) { - from = intIndex++; - filter = FLOAT_TO_INT; - } else if (ptype == long.class) { - from = longIndex++; - } else { - from = intIndex++; - ptype = int.class; - } - - permutePTypes[index] = ptype; - reorder[from] = index++; - - if (filter != null) { - filters[from] = filter; - hasFilters = true; - } - } - - if (hasFilters) { - initializer = MethodHandles.filterArguments(initializer, 0, filters); - } - - MethodType permutedMethodType = - methodType(initializer.type().returnType(), permutePTypes); - initializer = MethodHandles.permuteArguments(initializer, - permutedMethodType, reorder); - initializer = MethodHandles.explicitCastArguments(initializer, - methodType(CarrierObject.class, ptypes).insertParameterTypes(0, CarrierObject.class)); - - return initializer; - } - - /** - * Given components array, recast and reorder components to match shape. - * - * @param carrierShape carrier reshape - * @param components carrier components to reshape - * - * @return list of components reshaped - */ - static List reshapeComponents(CarrierShape carrierShape, - MethodHandle[] components) { - int count = carrierShape.count(); - Class[] ptypes = carrierShape.ptypes(); - MethodHandle[] reorder = new MethodHandle[count]; - int objectIndex = carrierShape.objectOffset(); - int intIndex = carrierShape.intOffset(); - int longIndex = carrierShape.longOffset(); - int index = 0; - - for (Class ptype : ptypes) { - MethodHandle component; - - if (!ptype.isPrimitive()) { - component = components[objectIndex++]; - } else if (ptype == double.class) { - component = MethodHandles.filterReturnValue( - components[longIndex++], LONG_TO_DOUBLE); - } else if (ptype == float.class) { - component = MethodHandles.filterReturnValue( - components[intIndex++], INT_TO_FLOAT); - } else if (ptype == long.class) { - component = components[longIndex++]; - } else { - component = components[intIndex++]; - } - - MethodType methodType = methodType(ptype, CarrierObject.class); - reorder[index++] = - MethodHandles.explicitCastArguments(component, methodType); - } - - return List.of(reorder); - } - - /** - * Factory for carriers that are backed by long[] and Object[]. - */ - static final class CarrierObjectFactory { - /** - * Unsafe access. - */ - private static final Unsafe UNSAFE; - - /* - * Constructor accessor MethodHandles. - */ - private static final MethodHandle CONSTRUCTOR; - private static final MethodHandle GET_LONG; - private static final MethodHandle PUT_LONG; - private static final MethodHandle GET_INTEGER; - private static final MethodHandle PUT_INTEGER; - private static final MethodHandle GET_OBJECT; - private static final MethodHandle PUT_OBJECT; - - static { - try { - UNSAFE = Unsafe.getUnsafe(); - Lookup lookup = MethodHandles.lookup(); - CONSTRUCTOR = lookup.findConstructor(CarrierObject.class, - methodType(void.class, int.class, int.class)); - GET_LONG = lookup.findVirtual(CarrierObject.class, "getLong", - methodType(long.class, int.class)); - PUT_LONG = lookup.findVirtual(CarrierObject.class, "putLong", - methodType(CarrierObject.class, int.class, long.class)); - GET_INTEGER = lookup.findVirtual(CarrierObject.class, "getInteger", - methodType(int.class, int.class)); - PUT_INTEGER = lookup.findVirtual(CarrierObject.class, "putInteger", - methodType(CarrierObject.class, int.class, int.class)); - GET_OBJECT = lookup.findVirtual(CarrierObject.class, "getObject", - methodType(Object.class, int.class)); - PUT_OBJECT = lookup.findVirtual(CarrierObject.class, "putObject", - methodType(CarrierObject.class, int.class, Object.class)); - } catch (ReflectiveOperationException ex) { - throw new AssertionError("carrier static init fail", ex); - } - } - - /** - * Constructor builder. - * - * @param carrierShape carrier object shape - * - * @return {@link MethodHandle} to generic carrier constructor. - */ - MethodHandle constructor(CarrierShape carrierShape) { - int objectCount = carrierShape.objectCount(); - int primitiveCount = carrierShape.primitiveCount(); - - MethodHandle constructor = MethodHandles.insertArguments(CONSTRUCTOR, - 0, primitiveCount, objectCount); - - return constructor; - } - - /** - * Adds constructor arguments for each of the allocated slots. - * - * @param carrierShape carrier object shape - * - * @return {@link MethodHandle} to specific carrier constructor. - */ - MethodHandle initializer(CarrierShape carrierShape) { - int longCount = carrierShape.longCount(); - int intCount = carrierShape.intCount(); - int objectCount = carrierShape.objectCount(); - MethodHandle initializer = MethodHandles.identity(CarrierObject.class); - - // long array index - int index = 0; - for (int i = 0; i < longCount; i++) { - MethodHandle put = MethodHandles.insertArguments(PUT_LONG, 1, index++); - initializer = MethodHandles.collectArguments(put, 0, initializer); - } - - // transition to int array index (double number of longs) - index *= LONG_SLOTS; - for (int i = 0; i < intCount; i++) { - MethodHandle put = MethodHandles.insertArguments(PUT_INTEGER, 1, index++); - initializer = MethodHandles.collectArguments(put, 0, initializer); - } - - for (int i = 0; i < objectCount; i++) { - MethodHandle put = MethodHandles.insertArguments(PUT_OBJECT, 1, i); - initializer = MethodHandles.collectArguments(put, 0, initializer); - } - - return initializer; - } - - /** - * Utility to construct the basic accessors from the components. - * - * @param carrierShape carrier object shape - * - * @return array of carrier accessors - */ - MethodHandle[] createComponents(CarrierShape carrierShape) { - int longCount = carrierShape.longCount(); - int intCount = carrierShape.intCount(); - int objectCount = carrierShape.objectCount(); - MethodHandle[] components = - new MethodHandle[carrierShape.ptypes().length]; - - // long array index - int index = 0; - // component index - int comIndex = 0; - for (int i = 0; i < longCount; i++) { - components[comIndex++] = MethodHandles.insertArguments(GET_LONG, 1, index++); - } - - // transition to int array index (double number of longs) - index *= LONG_SLOTS; - for (int i = 0; i < intCount; i++) { - components[comIndex++] = MethodHandles.insertArguments(GET_INTEGER, 1, index++); - } - - for (int i = 0; i < objectCount; i++) { - components[comIndex++] = MethodHandles.insertArguments(GET_OBJECT, 1, i); - } - return components; - } - - /** - * Cache mapping {@link MethodType} to previously defined {@link CarrierElements}. - */ - private static final Map - methodTypeCache = ReferencedKeyMap.create(false, ConcurrentHashMap::new); - - /** - * Permute a raw constructor and component accessor {@link MethodHandle MethodHandles} to - * match the order and types of the parameter types. - * - * @param carrierShape carrier object shape - * - * @return {@link CarrierElements} instance - */ - CarrierElements carrier(CarrierShape carrierShape) { - return methodTypeCache.computeIfAbsent(carrierShape.methodType, (mt) -> { - MethodHandle constructor = constructor(carrierShape); - MethodHandle initializer = initializer(carrierShape); - MethodHandle[] components = createComponents(carrierShape); - return new CarrierElements( - carrierShape, - CarrierObject.class, - constructor, - reshapeInitializer(carrierShape, initializer), - reshapeComponents(carrierShape, components)); - }); - } - } - - /** - * Wrapper object for carrier data. Instance types are stored in the {@code objects} - * array, while primitive types are recast to {@code int/long} and stored in the - * {@code primitives} array. Primitive byte, short, char, boolean and int are stored as - * integers. Longs and doubles are stored as longs. Longs take up the first part of the - * primitives array using normal indices. Integers follow using int[] indices offset beyond - * the longs using unsafe getInt/putInt. - */ - static class CarrierObject { - /** - * Carrier for primitive values. - */ - private final long[] primitives; - - /** - * Carrier for objects; - */ - private final Object[] objects; - - /** - * Constructor. - * - * @param primitiveCount slot count required for primitives - * @param objectCount slot count required for objects - */ - protected CarrierObject(int primitiveCount, int objectCount) { - this.primitives = createPrimitivesArray(primitiveCount); - this.objects = createObjectsArray(objectCount); - } - - /** - * Create a primitives array of an appropriate length. - * - * @param primitiveCount slot count required for primitives - * - * @return primitives array of an appropriate length. - */ - private long[] createPrimitivesArray(int primitiveCount) { - return primitiveCount != 0 ? new long[(primitiveCount + 1) / LONG_SLOTS] : null; - } - - /** - * Create a objects array of an appropriate length. - * - * @param objectCount slot count required for objects - * - * @return objects array of an appropriate length. - */ - private Object[] createObjectsArray(int objectCount) { - return objectCount != 0 ? new Object[objectCount] : null; - } - - /** - * Compute offset for unsafe access to long. - * - * @param i index in primitive[] - * - * @return offset for unsafe access - */ - private static long offsetToLong(int i) { - return Unsafe.ARRAY_LONG_BASE_OFFSET + - (long)i * Unsafe.ARRAY_LONG_INDEX_SCALE; - } - - /** - * Compute offset for unsafe access to int. - * - * @param i index in primitive[] - * - * @return offset for unsafe access - */ - private static long offsetToInt(int i) { - return Unsafe.ARRAY_LONG_BASE_OFFSET + - (long)i * Unsafe.ARRAY_INT_INDEX_SCALE; - } - - /** - * Compute offset for unsafe access to object. - * - * @param i index in objects[] - * - * @return offset for unsafe access - */ - private static long offsetToObject(int i) { - return Unsafe.ARRAY_OBJECT_BASE_OFFSET + - (long)i * Unsafe.ARRAY_OBJECT_INDEX_SCALE; - } - - /** - * {@return long value at index} - * - * @param i array index - */ - private long getLong(int i) { - return CarrierObjectFactory.UNSAFE.getLong(primitives, offsetToLong(i)); - } - - /** - * Put a long value into the primitive[]. - * - * @param i array index - * @param value long value to store - * - * @return this object - */ - private CarrierObject putLong(int i, long value) { - CarrierObjectFactory.UNSAFE.putLong(primitives, offsetToLong(i), value); - - return this; - } - - /** - * {@return int value at index} - * - * @param i array index - */ - private int getInteger(int i) { - return CarrierObjectFactory.UNSAFE.getInt(primitives, offsetToInt(i)); - } - - /** - * Put a int value into the int[]. - * - * @param i array index - * @param value int value to store - * - * @return this object - */ - private CarrierObject putInteger(int i, int value) { - CarrierObjectFactory.UNSAFE.putInt(primitives, offsetToInt(i), value); - - return this; - } - - /** - * {@return Object value at index} - * - * @param i array index - */ - private Object getObject(int i) { - return CarrierObjectFactory.UNSAFE.getReference(objects, offsetToObject(i)); - } - - /** - * Put a object value into the objects[]. - * - * @param i array index - * @param value object value to store - * - * @return this object - */ - private CarrierObject putObject(int i, Object value) { - CarrierObjectFactory.UNSAFE.putReference(objects, offsetToObject(i), value); - - return this; - } - } - - /** - * Class used to tally and track the number of ints, longs and objects. - * - * @param longCount number of longs and doubles - * @param intCount number of byte, short, int, chars and booleans - * @param objectCount number of objects - */ - private record CarrierCounts(int longCount, int intCount, int objectCount) { - /** - * Count the number of fields required in each of Object, int and long. - * - * @param ptypes parameter types - * - * @return a {@link CarrierCounts} instance containing counts - */ - static CarrierCounts tally(Class[] ptypes) { - return tally(ptypes, ptypes.length); - } - - /** - * Count the number of fields required in each of Object, int and long - * limited to the first {@code n} parameters. - * - * @param ptypes parameter types - * @param n number of parameters to check - * - * @return a {@link CarrierCounts} instance containing counts - */ - private static CarrierCounts tally(Class[] ptypes, int n) { - int longCount = 0; - int intCount = 0; - int objectCount = 0; - - for (int i = 0; i < n; i++) { - Class ptype = ptypes[i]; - - if (!ptype.isPrimitive()) { - objectCount++; - } else if (ptype == long.class || ptype == double.class) { - longCount++; - } else { - intCount++; - } - } - - return new CarrierCounts(longCount, intCount, objectCount); - } - - /** - * {@return total number of components} - */ - private int count() { - return longCount + intCount + objectCount; - } - - /** - * {@return total number of slots} - */ - private int slotCount() { - return longCount * LONG_SLOTS + intCount + objectCount; - } - - } - - /** - * Constructor - */ - private Carriers() { - throw new AssertionError("private constructor"); - } - - /** - * Shape of carrier based on counts of each of the three fundamental data - * types. - */ - private static class CarrierShape { - /** - * {@link MethodType} providing types for the carrier's components. - */ - final MethodType methodType; - - /** - * Counts of different parameter types. - */ - final CarrierCounts counts; - - /** - * Constructor. - * - * @param methodType {@link MethodType} providing types for the - * carrier's components - */ - public CarrierShape(MethodType methodType) { - this.methodType = methodType; - this.counts = CarrierCounts.tally(methodType.parameterArray()); - } - - /** - * {@return number of long fields needed} - */ - int longCount() { - return counts.longCount(); - } - - /** - * {@return number of int fields needed} - */ - int intCount() { - return counts.intCount(); - } - - /** - * {@return number of object fields needed} - */ - int objectCount() { - return counts.objectCount(); - } - - /** - * {@return slot count required for primitives} - */ - int primitiveCount() { - return counts.longCount() * LONG_SLOTS + counts.intCount(); - } - - /** - * {@return array of parameter types} - */ - Class[] ptypes() { - return methodType.parameterArray(); - } - - /** - * {@return number of components} - */ - int count() { - return counts.count(); - } - - /** - * {@return number of slots used} - */ - int slotCount() { - return counts.slotCount(); - } - - /** - * {@return index of first long component} - */ - int longOffset() { - return 0; - } - - /** - * {@return index of first int component} - */ - int intOffset() { - return longCount(); - } - - /** - * {@return index of first object component} - */ - int objectOffset() { - return longCount() + intCount(); - } - } - - /** - * This factory class generates {@link CarrierElements} instances containing the - * {@link MethodHandle MethodHandles} to the constructor and accessors of a carrier - * object. - *

- * Clients can create instances by describing a carrier shape, that - * is, a {@linkplain MethodType method type} whose parameter types describe the types of - * the carrier component values, or by providing the parameter types directly. - */ - static final class CarrierFactory { - /** - * Constructor - */ - private CarrierFactory() { - throw new AssertionError("private constructor"); - } - - private static final CarrierObjectFactory FACTORY = new CarrierObjectFactory(); - - /** - * Factory method to return a {@link CarrierElements} instance that matches the shape of - * the supplied {@link MethodType}. The return type of the {@link MethodType} is ignored. - * - * @param methodType {@link MethodType} whose parameter types supply the - * the shape of the carrier's components - * - * @return {@link CarrierElements} instance - * - * @throws NullPointerException is methodType is null - * @throws IllegalArgumentException if number of component slots exceeds maximum - */ - static CarrierElements of(MethodType methodType) { - Objects.requireNonNull(methodType, "methodType must not be null"); - MethodType constructorMT = methodType.changeReturnType(Object.class); - CarrierShape carrierShape = new CarrierShape(constructorMT); - int slotCount = carrierShape.slotCount(); - - if (MAX_COMPONENTS < slotCount) { - throw new IllegalArgumentException("Exceeds maximum number of component slots"); - } - - return FACTORY.carrier(carrierShape); - } - - /** - * Factory method to return a {@link CarrierElements} instance that matches the shape of - * the supplied parameter types. - * - * @param ptypes parameter types that supply the shape of the carrier's components - * - * @return {@link CarrierElements} instance - * - * @throws NullPointerException is ptypes is null - * @throws IllegalArgumentException if number of component slots exceeds maximum - */ - static CarrierElements of(Class...ptypes) { - Objects.requireNonNull(ptypes, "ptypes must not be null"); - return of(methodType(Object.class, ptypes)); - } - } - - /** - * Instances of this class provide the {@link MethodHandle MethodHandles} to the - * constructor and accessors of a carrier object. The original component types can be - * gleaned from the parameter types of the constructor {@link MethodHandle} or by the - * return types of the components' {@link MethodHandle MethodHandles}. - */ - static final class CarrierElements { - /** - * Slot count required for objects. - */ - private final int objectCount; - - /** - * Slot count required for primitives. - */ - private final int primitiveCount; - - /** - * Underlying carrier class. - */ - private final Class carrierClass; - - /** - * Constructor {@link MethodHandle}. - */ - private final MethodHandle constructor; - - /** - * Initializer {@link MethodHandle}. - */ - private final MethodHandle initializer; - - /** - * List of component {@link MethodHandle MethodHandles} - */ - private final List components; - - /** - * Constructor - */ - private CarrierElements() { - throw new AssertionError("private constructor"); - } - - /** - * Constructor - */ - CarrierElements(CarrierShape carrierShape, - Class carrierClass, - MethodHandle constructor, - MethodHandle initializer, - List components) { - this.objectCount = carrierShape.objectCount(); - this.primitiveCount = carrierShape.primitiveCount(); - this.carrierClass = carrierClass; - this.constructor = constructor; - this.initializer = initializer; - this.components = components; - } - - /** - * {@return slot count required for objects} - */ - int objectCount() { - return objectCount; - } - - /** - * {@return slot count required for primitives} - */ - int primitiveCount() { - return primitiveCount; - } - - /** - * {@return the underlying carrier class} - */ - Class carrierClass() { - return carrierClass; - } - - /** - * {@return the constructor {@link MethodHandle} for the carrier. The - * carrier constructor will always have a return type of {@link Object} } - */ - MethodHandle constructor() { - return constructor; - } - - /** - * {@return the initializer {@link MethodHandle} for the carrier} - */ - MethodHandle initializer() { - return initializer; - } - - /** - * Return the constructor plus initializer {@link MethodHandle} for the carrier. - * The {@link MethodHandle} will always have a return type of {@link Object}. - * @return the constructor plus initializer {@link MethodHandle} - */ - MethodHandle initializingConstructor() { - return MethodHandles.foldArguments(initializer, 0, constructor); - } - - /** - * {@return immutable list of component accessor {@link MethodHandle MethodHandles} - * for all the carrier's components. The receiver type of the accessors - * will always be {@link Object} } - */ - List components() { - return components; - } - - /** - * {@return a component accessor {@link MethodHandle} for component {@code i}. - * The receiver type of the accessor will be {@link Object} } - * - * @param i component index - * - * @throws IllegalArgumentException if {@code i} is out of bounds - */ - MethodHandle component(int i) { - if (i < 0 || components.size() <= i) { - throw new IllegalArgumentException("i is out of bounds " + i + - " of " + components.size()); - } - - return components.get(i); - } - - @Override - public String toString() { - return "Carrier" + constructor.type().parameterList(); - } - } - - /** - * {@return the underlying carrier class of the carrier representing {@code methodType} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - */ - static Class carrierClass(MethodType methodType) { - return CarrierFactory.of(methodType).carrierClass(); - } - - /** - * {@return the constructor {@link MethodHandle} for the carrier representing {@code - * methodType}. The carrier constructor will always have a return type of {@link Object} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - */ - static MethodHandle constructor(MethodType methodType) { - MethodHandle constructor = CarrierFactory.of(methodType).constructor(); - constructor = constructor.asType(constructor.type().changeReturnType(Object.class)); - return constructor; - } - - /** - * {@return the initializer {@link MethodHandle} for the carrier representing {@code - * methodType}. The carrier initializer will always take an {@link Object} along with - * component values and a return type of {@link Object} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - */ - static MethodHandle initializer(MethodType methodType) { - MethodHandle initializer = CarrierFactory.of(methodType).initializer(); - initializer = initializer.asType(initializer.type() - .changeReturnType(Object.class).changeParameterType(0, Object.class)); - return initializer; - } - - /** - * {@return the combination {@link MethodHandle} of the constructor and initializer - * for the carrier representing {@code methodType}. The carrier constructor/initializer - * will always take the component values and a return type of {@link Object} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - */ - static MethodHandle initializingConstructor(MethodType methodType) { - MethodHandle constructor = CarrierFactory.of(methodType).initializingConstructor(); - constructor = constructor.asType(constructor.type().changeReturnType(Object.class)); - return constructor; - } - - /** - * {@return immutable list of component accessor {@link MethodHandle MethodHandles} for - * all the components of the carrier representing {@code methodType}. The receiver type of - * the accessors will always be {@link Object} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - */ - static List components(MethodType methodType) { - return CarrierFactory - .of(methodType) - .components() - .stream() - .map(c -> c.asType(c.type().changeParameterType(0, Object.class))) - .toList(); - } - - /** - * {@return a component accessor {@link MethodHandle} for component {@code i} of the - * carrier representing {@code methodType}. The receiver type of the accessor will always - * be {@link Object} } - * - * @param methodType {@link MethodType} whose parameter types supply the shape of the - * carrier's components - * @param i component index - * - * @throws IllegalArgumentException if {@code i} is out of bounds - */ - static MethodHandle component(MethodType methodType, int i) { - MethodHandle component = CarrierFactory.of(methodType).component(i); - component = component.asType(component.type().changeParameterType(0, Object.class)); - return component; - } - -} diff --git a/src/java.base/share/classes/java/nio/file/TempFileHelper.java b/src/java.base/share/classes/java/nio/file/TempFileHelper.java index e5ba85fcf364..b9be8ed243a7 100644 --- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java +++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ private static Path generatePath(String prefix, String suffix, Path dir) { String s = prefix + Long.toUnsignedString(n) + suffix; Path name = dir.getFileSystem().getPath(s); // the generated name should be a simple file name - if (name.getParent() != null) + if (name.getParent() != null || name.getRoot() != null) throw new IllegalArgumentException("Invalid prefix or suffix"); return dir.resolve(name); } diff --git a/src/java.base/share/classes/java/security/BinaryEncodable.java b/src/java.base/share/classes/java/security/BinaryEncodable.java index a1713c413ba1..011c511f0434 100644 --- a/src/java.base/share/classes/java/security/BinaryEncodable.java +++ b/src/java.base/share/classes/java/security/BinaryEncodable.java @@ -31,27 +31,27 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; -import jdk.internal.javac.PreviewFeature; import sun.security.internal.InternalBinaryEncodable; - /** - * This interface identifies the cryptographic objects that can be converted - * to and from binary data, and thereby encoded and decoded as PEM text. + * This interface identifies cryptographic objects that can be converted to + * and from standardized binary representations. * *

The APIs for cryptographic objects such as public keys, private keys, * certificates, and certificate revocation lists all provide the means to * convert their instances to and from standardized binary representations. * Other kinds of cryptographic objects, such as certificate requests, have * no corresponding API but can still be expressed as standardized binary - * representations. The {@code BinaryEncodable} interface allows the - * {@link PEMEncoder} and {@link PEMDecoder} classes to operate uniformly on - * binary representations of key or certificate material. + * representations. The {@code BinaryEncodable} interface allows APIs that + * operate on standardized binary representations, such as {@link PEMEncoder} + * and {@link PEMDecoder}, to process all kinds of cryptographic objects + * uniformly. * *

The permitted subtype {@code PEM} is notable for supporting the encoding * and decoding of PEM text that represents cryptographic objects for which no * API exists. In future releases, other permitted subtypes may be added to - * support the encoding and decoding of such cryptographic objects. + * support the encoding and decoding of additional kinds of cryptographic + * objects as standardized binary representations. * *

The list of permitted subtypes shown after {@code permits} is not * exhaustive. This means if application code switches over a @@ -71,10 +71,9 @@ * @see X509CRL * @see PEM * - * @since 27 + * @since 28 */ -@PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public sealed interface BinaryEncodable permits AsymmetricKey, KeyPair, PKCS8EncodedKeySpec, X509EncodedKeySpec, EncryptedPrivateKeyInfo, X509Certificate, X509CRL, PEM, InternalBinaryEncodable { diff --git a/src/java.base/share/classes/java/security/PEM.java b/src/java.base/share/classes/java/security/PEM.java index 421ae40b30f2..87aa857ff7ff 100644 --- a/src/java.base/share/classes/java/security/PEM.java +++ b/src/java.base/share/classes/java/security/PEM.java @@ -25,8 +25,6 @@ package java.security; -import jdk.internal.javac.PreviewFeature; - import jdk.internal.ref.CleanerFactory; import sun.security.util.KeyUtil; import sun.security.util.Pem; @@ -72,9 +70,8 @@ * @see PEMDecoder * @see PEMEncoder * - * @since 26 + * @since 28 */ -@PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public final class PEM implements BinaryEncodable { private final String type; @@ -133,8 +130,6 @@ public PEM(String type, String base64Content) { * @throws IllegalArgumentException if {@code type} contains PEM * encapsulation syntax * @throws NullPointerException if any parameter is {@code null} - * - * @since 27 */ public PEM(String type, byte[] base64Content, byte[] leadingData) { this(type, base64Content); @@ -153,8 +148,6 @@ public PEM(String type, byte[] base64Content, byte[] leadingData) { * @throws IllegalArgumentException if {@code type} contains PEM * encapsulation syntax * @throws NullPointerException if any parameter is {@code null} - * - * @since 27 */ public PEM(String type, byte[] base64Content) { Objects.requireNonNull(type, "type cannot be null"); @@ -198,8 +191,6 @@ public byte[] leadingData() { * Returns the Base64-encoded content. * * @return a newly-allocated byte array containing the Base64 content - * - * @since 27 */ public byte[] content() { try { diff --git a/src/java.base/share/classes/java/security/PEMDecoder.java b/src/java.base/share/classes/java/security/PEMDecoder.java index 8ebc83f93d10..dfd0a9d4094c 100644 --- a/src/java.base/share/classes/java/security/PEMDecoder.java +++ b/src/java.base/share/classes/java/security/PEMDecoder.java @@ -25,8 +25,6 @@ package java.security; -import jdk.internal.javac.PreviewFeature; - import jdk.internal.ref.CleanerFactory; import sun.security.pkcs.PKCS8Key; import sun.security.rsa.RSAPrivateCrtKeyImpl; @@ -147,9 +145,8 @@ * @spec https://www.rfc-editor.org/info/rfc7468 * RFC 7468: Textual Encodings of PKIX, PKCS, and CMS Structures * - * @since 25 + * @since 28 */ -@PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public final class PEMDecoder { private final Provider factory; private final PBEKeySpec keySpec; @@ -294,8 +291,6 @@ yield new KeyPair(getKeyFactory(algo). * @throws IllegalArgumentException if decoding fails or no PEM data is found * @throws NullPointerException if {@code str} is {@code null} * @throws CryptoException if an error occurs during decryption - * - * @since 27 */ public BinaryEncodable decode(String str) { Objects.requireNonNull(str); @@ -335,8 +330,6 @@ public BinaryEncodable decode(String str) { * @throws IllegalArgumentException if decoding fails * @throws NullPointerException if {@code InputStream} is {@code null} * @throws CryptoException if an error occurs during decryption - * - * @since 27 */ public BinaryEncodable decode(InputStream is) throws IOException { Objects.requireNonNull(is); @@ -379,8 +372,6 @@ public BinaryEncodable decode(InputStream is) throws IOException { * @throws ClassCastException if {@code tClass} does not represent the PEM type * @throws NullPointerException if any input values are {@code null} * @throws CryptoException if an error occurs during decryption - * - * @since 27 */ public S decode(String str, Class tClass) { Objects.requireNonNull(str); @@ -428,8 +419,6 @@ public S decode(String str, Class tClass) { * * @see #decode(InputStream) * @see #decode(String, Class) - * - * @since 27 */ public S decode(InputStream is, Class tClass) throws IOException { @@ -543,8 +532,6 @@ private CertificateFactory getCertFactory(String algorithm) { * @param provider the factory {@code Provider} * @return a new {@code PEMDecoder} instance configured with the {@code Provider} * @throws NullPointerException if {@code provider} is {@code null} - * - * @since 27 */ public PEMDecoder withFactoriesOf(Provider provider) { Objects.requireNonNull(provider); diff --git a/src/java.base/share/classes/java/security/PEMEncoder.java b/src/java.base/share/classes/java/security/PEMEncoder.java index 211b47008a5f..2066c3a3d987 100644 --- a/src/java.base/share/classes/java/security/PEMEncoder.java +++ b/src/java.base/share/classes/java/security/PEMEncoder.java @@ -25,8 +25,6 @@ package java.security; -import jdk.internal.javac.PreviewFeature; - import jdk.internal.ref.CleanerFactory; import sun.security.pkcs.PKCS8Key; import sun.security.util.KeyUtil; @@ -117,9 +115,8 @@ * @spec https://www.rfc-editor.org/info/rfc7468 * RFC 7468: Textual Encodings of PKIX, PKCS, and CMS Structures * - * @since 25 + * @since 28 */ -@PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public final class PEMEncoder { // Singleton instance of PEMEncoder @@ -169,8 +166,6 @@ public static PEMEncoder of() { * @throws NullPointerException if {@code be} is {@code null} * @throws CryptoException if an error occurs during encryption * @see #withEncryption(char[]) - * - * @since 27 */ public String encodeToString(BinaryEncodable be) { Objects.requireNonNull(be); @@ -196,8 +191,6 @@ public String encodeToString(BinaryEncodable be) { * @throws NullPointerException if {@code be} is {@code null} * @throws CryptoException if an error occurs during encryption * @see #withEncryption(char[]) - * - * @since 27 */ public byte[] encode(BinaryEncodable be) { return switch (be) { diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java index 6e02c3f5a238..b03c683180f7 100644 --- a/src/java.base/share/classes/java/util/Properties.java +++ b/src/java.base/share/classes/java/util/Properties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,8 +239,8 @@ public synchronized Object setProperty(String key, String value) { * Properties are processed in terms of lines. There are two * kinds of lines, natural lines and logical lines. * A natural line is defined as a line of - * characters that is terminated either by a set of line terminator - * characters ({@code \n} or {@code \r} or {@code \r\n}) + * characters that is terminated either by a line terminator + * sequence ({@code \n}, {@code \r}, or {@code \r\n}) * or by the end of the stream. A natural line may be either a blank line, * a comment line, or hold all or some of a key-element pair. A logical * line holds all the data of a key-element pair, which may be spread @@ -266,7 +266,7 @@ public synchronized Object setProperty(String key, String value) { *

* If a logical line is spread across several natural lines, the * backslash escaping the line terminator sequence, the line - * terminator sequence, and any white space at the start of the + * terminator sequence itself, and any white space at the start of the * following line have no effect on the key or element values. * The remainder of the discussion of key and element parsing * (when loading) will assume all the characters constituting diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index f39d92aeeb40..b985c4eb4b82 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -448,7 +448,7 @@ else if (deadline != 0L) { Aux next = a.next; if (a == node) { if (prev != null) - prev.casNext(prev, next); + prev.casNext(a, next); else if (casAux(a, next)) break clean; break; // check for failed or stale CAS diff --git a/src/java.base/share/classes/javax/crypto/CryptoException.java b/src/java.base/share/classes/javax/crypto/CryptoException.java index 367417abf9dd..86ac616b9147 100644 --- a/src/java.base/share/classes/javax/crypto/CryptoException.java +++ b/src/java.base/share/classes/javax/crypto/CryptoException.java @@ -25,8 +25,6 @@ package javax.crypto; -import jdk.internal.javac.PreviewFeature; - /** * Thrown to indicate a cryptographic failure during processing. * @@ -38,9 +36,8 @@ *

This exception is not intended to represent internal provider errors, * which should be reported using {@link java.security.ProviderException}. * - * @since 27 + * @since 28 */ -@PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public final class CryptoException extends RuntimeException { @java.io.Serial diff --git a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java index 632c81eab169..64eb2d79922d 100644 --- a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java +++ b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java @@ -25,8 +25,6 @@ package javax.crypto; -import jdk.internal.javac.PreviewFeature; - import sun.security.jca.JCAUtil; import sun.security.pkcs.PKCS8Key; import sun.security.util.*; @@ -368,9 +366,8 @@ private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey, * not supported by any provider, or if an error occurs during * encryption * - * @since 27 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public static EncryptedPrivateKeyInfo encrypt(BinaryEncodable be, char[] password, String algorithm, AlgorithmParameterSpec params, Provider provider) { @@ -411,9 +408,8 @@ public static EncryptedPrivateKeyInfo encrypt(BinaryEncodable be, * defines the default encryption algorithm. The {@code AlgorithmParameterSpec} * defaults are determined by the provider. * - * @since 27 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public static EncryptedPrivateKeyInfo encrypt(BinaryEncodable be, char[] password) { return encrypt(be, password, Pem.DEFAULT_ALGO, null, @@ -450,9 +446,8 @@ public static EncryptedPrivateKeyInfo encrypt(BinaryEncodable be, * {@code algorithm} or {@code params} are not supported by any * provider, or if an error occurs during encryption * - * @since 27 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public static EncryptedPrivateKeyInfo encrypt(BinaryEncodable be, Key encryptKey, String algorithm, AlgorithmParameterSpec params, Provider provider, SecureRandom random) { @@ -520,9 +515,8 @@ private static EncryptedPrivateKeyInfo encryptImpl(byte[] encoded, * @throws InvalidKeyException if an error occurs during parsing, * decryption, or key generation * - * @since 25 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public PrivateKey getKey(char[] password) throws NoSuchAlgorithmException, InvalidKeyException { Objects.requireNonNull(password, "a password must be specified"); @@ -548,9 +542,8 @@ public PrivateKey getKey(char[] password) * @throws InvalidKeyException if an error occurs during parsing, * decryption, or key generation * - * @since 27 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public PrivateKey getKey(Key decryptKey) throws NoSuchAlgorithmException, InvalidKeyException { Objects.requireNonNull(decryptKey,"a decryptKey must be specified"); @@ -576,9 +569,8 @@ public PrivateKey getKey(Key decryptKey) * @throws InvalidKeyException if the encoded data lacks a public key, or if * an error occurs during parsing, decryption, or key generation * - * @since 26 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public KeyPair getKeyPair(char[] password) throws NoSuchAlgorithmException, InvalidKeyException { Objects.requireNonNull(password, "a password must be specified"); @@ -614,9 +606,8 @@ public KeyPair getKeyPair(char[] password) * @throws InvalidKeyException if the encoded data lacks a public key, or if * an error occurs during parsing, decryption, or key generation * - * @since 27 + * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public KeyPair getKeyPair(Key decryptKey) throws NoSuchAlgorithmException, InvalidKeyException { Objects.requireNonNull(decryptKey,"a decryptKey must be specified"); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java b/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java index 3f528ebd6b1c..9209196f98fe 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java @@ -404,13 +404,27 @@ public int getIntUnchecked(int bci) { } // non-wide branches + // dest() on validated payload only public int dest() { - return bci + getShortUnchecked(bci + 1); + int offset = getOffsetS2(); + assert -0xFFFF <= offset && offset <= 0xFFFF; + return bci + offset; + } + + public int getOffsetS2() { + return getShortUnchecked(bci + 1); } // goto_w and jsr_w + // destW() on validated payload only public int destW() { - return bci + getIntUnchecked(bci + 1); + int offset = getOffsetS4(); + assert -0xFFFF <= offset && offset <= 0xFFFF; + return bci + offset; + } + + public int getOffsetS4() { + return getIntUnchecked(bci + 1); } // *load, *store, iinc @@ -477,7 +491,7 @@ private int checkSpecialInstruction(int bci, int end, int code) { } } else if (code == LOOKUPSWITCH) { int alignedBci = align(bci + 1); - if (alignedBci + 2 * 4 < end) { + if (alignedBci + 2 * 4 <= end) { int npairs = getIntUnchecked(alignedBci + 4); if (npairs >= 0) { long l = alignedBci - bci + (2L + 2L * npairs) * 4L; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java index d096b78a67d4..4417dbaaa401 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.lang.classfile.constantpool.NameAndTypeEntry; import java.lang.classfile.constantpool.Utf8Entry; import java.util.Arrays; +import java.util.HashSet; import java.util.Set; import jdk.internal.classfile.impl.TemporaryConstantPool; @@ -56,7 +57,7 @@ public VerificationFrame(int offset, int flags, int locals_size, int stack_size, this._flags = flags; this._locals = locals; this._stack = stack; - this._assert_unset_fields = assert_unset_fields; + set_assert_unset_fields(assert_unset_fields); this._verifier = v; } @@ -122,7 +123,7 @@ Set assert_unset_fields() { } void set_assert_unset_fields(Set table) { - _assert_unset_fields = table; + _assert_unset_fields = new HashSet<>(table); } // Called when verifying putfields to mark strict instance fields as satisfied @@ -184,6 +185,9 @@ void push_stack(VerificationType type) { if (_stack_size >= _max_stack) { _verifier.verifyError("Operand stack overflow"); } + if (type.is_uninitialized_this(_verifier)) { + _flags |= FLAG_THIS_UNINIT; + } _stack[_stack_size++] = type; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java index fbb4eb9c9edb..ef18c4ff8c48 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,7 +135,14 @@ boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boo return result; } - void check_jump_target(VerificationFrame frame, int target) { + void check_jump_target(VerificationFrame frame, int bci, int offset) { + // Jump targets must be within the method and the method size is limited. See JVMS 4.11 + int min_offset = -1 * 0xFFFF; + if (offset < min_offset || offset > 0xFFFF) { + _verifier.verifyError("Illegal target of jump or branch (bci %d + offset %d)".formatted(bci, offset)); + return; + } + int target = bci + offset; boolean match = match_stackmap(frame, target, true, false); if (!match || (target < 0 || target >= _code_length)) { _verifier.verifyError(String.format("Inconsistent stackmap frames at branch target %d", target)); @@ -155,6 +162,7 @@ static class StackMapReader { final Set strictFields; Set _assert_unset_fields_buffer; boolean _first; + private boolean _uninit_in_prev_frame_locals; void check_verification_type_array_size(int size, int max_size) { if (size < 0 || size > max_size) { @@ -223,6 +231,15 @@ public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len, _cp = null; _frame_count = 0; } + + VerificationType[] locals = init_frame.locals(); + _uninit_in_prev_frame_locals = false; + for (int i = 0; i < init_frame.locals_size(); i++) { + if (locals[i].is_uninitialized_this(_verifier)) { + _uninit_in_prev_frame_locals = true; + break; + } + } } void check_offset(VerificationFrame frame) { @@ -252,7 +269,8 @@ int chop(VerificationType[] locals, int length, int chops) { return pos+1; } - VerificationType parse_verification_type(int[] flags) { + VerificationType parse_verification_type(int[] flags, boolean parsing_locals) { + assert flags != null; int tag = _stream.get_u1(); if (tag < ITEM_UNINITIALIZED_THIS) { return VerificationType.from_tag(tag, _verifier); @@ -266,8 +284,12 @@ VerificationType parse_verification_type(int[] flags) { return VerificationType.reference_type(_cp.classNameAt(class_index)); } if (tag == ITEM_UNINITIALIZED_THIS) { - if (flags != null) { - flags[0] |= VerificationFrame.FLAG_THIS_UNINIT; + flags[0] |= VerificationFrame.FLAG_THIS_UNINIT; + // An uninitializedThis in the locals array can sometimes be preserved + // between frames while uninitializedThis in the stack cannot as the stack + // is cleared. Chop and Full frames need special handling. + if (parsing_locals) { + _uninit_in_prev_frame_locals = true; } return VerificationType.uninitialized_this_type; } @@ -332,7 +354,10 @@ VerificationFrame next_helper() { offset = _prev_frame.offset() + frame_type + 1; locals = _prev_frame.locals(); } - frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier); + + int flags = _uninit_in_prev_frame_locals ? 1 : 0; + + frame = new VerificationFrame(offset, flags, _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier); if (_first && locals != null) { frame.copy_locals(_prev_frame); } @@ -351,13 +376,14 @@ VerificationFrame next_helper() { } VerificationType[] stack = new VerificationType[2]; int stack_size = 1; - stack[0] = parse_verification_type(null); + int[] flags = {_uninit_in_prev_frame_locals ? 1 : 0}; + stack[0] = parse_verification_type(flags, false /*parsing_locals*/); if (stack[0].is_category2()) { stack[1] = stack[0].to_category2_2nd(_verifier); stack_size = 2; } check_verification_type_array_size(stack_size, _max_stack); - frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier); + frame = new VerificationFrame(offset, flags[0], _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier); if (_first && locals != null) { frame.copy_locals(_prev_frame); } @@ -380,13 +406,14 @@ VerificationFrame next_helper() { } VerificationType[] stack = new VerificationType[2]; int stack_size = 1; - stack[0] = parse_verification_type(null); + int[] flags = {_uninit_in_prev_frame_locals ? 1 : 0}; + stack[0] = parse_verification_type(flags, false /*parsing_locals*/); if (stack[0].is_category2()) { stack[1] = stack[0].to_category2_2nd(_verifier); stack_size = 2; } check_verification_type_array_size(stack_size, _max_stack); - frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier); + frame = new VerificationFrame(offset, flags[0], _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier); if (_first && locals != null) { frame.copy_locals(_prev_frame); } @@ -398,14 +425,16 @@ VerificationFrame next_helper() { int length = _prev_frame.locals_size(); int chops = SAME_FRAME_EXTENDED - frame_type; int new_length = length; - int flags = _prev_frame.flags(); + int flags = _uninit_in_prev_frame_locals ? 1 : 0; if (chops != 0) { new_length = chop(locals, length, chops); check_verification_type_array_size(new_length, _max_locals); flags = 0; + _uninit_in_prev_frame_locals = false; for (int i=0; i 0) { @@ -464,7 +494,7 @@ VerificationFrame next_helper() { } int i; for (i=0; i strict_fields = new HashSet<>(); - if (m.name().equals(ConstantDescs.INIT_NAME)) { + // Hotspot runtime filters STRICT_INIT flag by classfile version, ClassFile API needs extra check + if (m.name().equals(ConstantDescs.INIT_NAME) && supports_strict_fields(_klass)) { for (var fs : current_class().clm.fields()) { if (fs.flags().has(AccessFlag.STRICT_INIT) && !fs.flags().has(AccessFlag.STATIC)) { var new_field = TemporaryConstantPool.INSTANCE.nameAndTypeEntry(fs.fieldName(), fs.fieldType()); @@ -331,6 +332,7 @@ void verify_method(VerificationWrapper.MethodWrapper m) { } } + Set read_only_strict_fields = new HashSet<>(strict_fields); VerificationFrame current_frame = new VerificationFrame(max_locals, max_stack, strict_fields, this); VerificationType return_type = current_frame.set_locals_from_arg(m, current_type()); int stackmap_index = 0; @@ -345,7 +347,7 @@ void verify_method(VerificationWrapper.MethodWrapper m) { verify_local_variable_table(code_length, code_data); var reader = new VerificationTable.StackMapReader(stackmap_data, code_data, code_length, current_frame, - (char) max_locals, (char) max_stack, strict_fields, cp, this); + (char) max_locals, (char) max_stack, read_only_strict_fields, cp, this); VerificationTable stackmap_table = new VerificationTable(reader, cp, this); var bcs = code.start(); @@ -361,7 +363,6 @@ void verify_method(VerificationWrapper.MethodWrapper m) { boolean verified_exc_handlers = false; { int index; - int target; VerificationType type, type2 = null; VerificationType atype; if (bcs.isWide()) { @@ -1069,9 +1070,8 @@ void verify_method(VerificationWrapper.MethodWrapper m) { case IFLE: current_frame.pop_stack( VerificationType.integer_type); - target = bcs.dest(); stackmap_table.check_jump_target( - current_frame, target); + current_frame, bcs.bci(), bcs.getOffsetS2()); no_control_flow = false; break; case IF_ACMPEQ : case IF_ACMPNE : @@ -1080,19 +1080,16 @@ void verify_method(VerificationWrapper.MethodWrapper m) { case IFNULL : case IFNONNULL : current_frame.pop_stack(object_type()); - target = bcs.dest(); stackmap_table.check_jump_target - (current_frame, target); + (current_frame, bcs.bci(), bcs.getOffsetS2()); no_control_flow = false; break; case GOTO : - target = bcs.dest(); stackmap_table.check_jump_target( - current_frame, target); + current_frame, bcs.bci(), bcs.getOffsetS2()); no_control_flow = true; break; case GOTO_W : - target = bcs.destW(); stackmap_table.check_jump_target( - current_frame, target); + current_frame, bcs.bci(), bcs.getOffsetS4()); no_control_flow = true; break; case TABLESWITCH : case LOOKUPSWITCH : @@ -1154,11 +1151,9 @@ void verify_method(VerificationWrapper.MethodWrapper m) { case INVOKEVIRTUAL : case INVOKESPECIAL : case INVOKESTATIC : - this_uninit = verify_invoke_instructions(bcs, code_length, current_frame, (bci >= ex_minmax[0] && bci < ex_minmax[1]), this_uninit, return_type, cp, stackmap_table); - no_control_flow = false; break; case INVOKEINTERFACE : case INVOKEDYNAMIC : - this_uninit = verify_invoke_instructions(bcs, code_length, current_frame, (bci >= ex_minmax[0] && bci < ex_minmax[1]), this_uninit, return_type, cp, stackmap_table); + this_uninit = verify_invoke_instructions(bcs, code_length, current_frame, (bci >= ex_minmax[0] && bci < ex_minmax[1]), this_uninit, cp, stackmap_table); no_control_flow = false; break; case NEW : { @@ -1475,12 +1470,11 @@ void verify_switch(RawBytecodeHelper bcs, int code_length, byte[] code_data, Ver } } } - int target = bci + default_offset; - stackmap_table.check_jump_target(current_frame, target); + stackmap_table.check_jump_target(current_frame, bci, default_offset); for (int i = 0; i < keys; i++) { aligned_bci = VerificationBytecodes.align(bcs.bci() + 1); - target = bci + bcs.getIntUnchecked(aligned_bci + (3+i*delta)*4); - stackmap_table.check_jump_target(current_frame, target); + int offset = bcs.getIntUnchecked(aligned_bci + (3+i*delta)*4); + stackmap_table.check_jump_target(current_frame, bci, offset); } } @@ -1533,7 +1527,8 @@ void verify_field_instructions(RawBytecodeHelper bcs, VerificationFrame current_ // Set the type to the current type so the is_assignable check passes. stack_object_type = current_type(); - if (fd.flags().has(AccessFlag.STRICT_INIT)) { + // Hotspot runtime filters STRICT_INIT flag by classfile version, ClassFile API needs extra check + if (fd.flags().has(AccessFlag.STRICT_INIT) && supports_strict_fields(_klass)) { current_frame.satisfy_unset_field(fd.fieldName(), fd.fieldType()); } } @@ -1607,7 +1602,7 @@ static boolean is_same_or_direct_interface(VerificationWrapper klass, Verificati return false; } - boolean verify_invoke_instructions(RawBytecodeHelper bcs, int code_length, VerificationFrame current_frame, boolean in_try_block, boolean this_uninit, VerificationType return_type, ConstantPoolWrapper cp, VerificationTable stackmap_table) { + boolean verify_invoke_instructions(RawBytecodeHelper bcs, int code_length, VerificationFrame current_frame, boolean in_try_block, boolean this_uninit, ConstantPoolWrapper cp, VerificationTable stackmap_table) { // Make sure the constant pool item is the right type int index = bcs.getIndexU2(); int opcode = bcs.opcode(); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md index 1899f7b86a37..dda8dea1e335 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md @@ -17,4 +17,4 @@ for example, this should not fail upon encountering new language features, and should at best include all new checks hotspot has as long as the required information are accessible to the Class-File API. -Last sync: jdk-26+5, July 3rd 2025 +Last sync: jdk-28+11, Aug 14th 2026 diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index 280070e187aa..bc7b77110a84 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -77,9 +77,6 @@ public enum Feature { STRUCTURED_CONCURRENCY, @JEP(number = 531, title = "Lazy Constants", status = "Third Preview") LAZY_CONSTANTS, - @JEP(number=538, title="PEM Encodings of Cryptographic Objects", - status="Third Preview") - PEM_API, /** * Indicates a preview API exists to allow access to the environment * where all preview features of the current Java SE release are enabled. diff --git a/src/java.base/share/classes/jdk/internal/misc/CDS.java b/src/java.base/share/classes/jdk/internal/misc/CDS.java index b61743c1fb3e..42c8cb5612ba 100644 --- a/src/java.base/share/classes/jdk/internal/misc/CDS.java +++ b/src/java.base/share/classes/jdk/internal/misc/CDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.InputStream; import java.io.IOException; import java.io.PrintStream; +import java.net.JarURLConnection; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -399,6 +401,30 @@ public static boolean needsClassInitBarrier(Class c) { private static native boolean needsClassInitBarrier0(Class c); + /** + * Returns a resource located in a JAR file + * @param loader Class loader used by AOT + * @param jarURL URL of JAR archive which should contain the resource + * @param name Resource name + */ + public static URL getResource(ClassLoader loader, URL jarURL, String name) throws Exception { + URL resource = loader.getResource(name); + + if (resource != null) { + // If the resource is not in the correct JAR file, discard it + if (resource.getProtocol().equalsIgnoreCase("jar")) { + JarURLConnection resourceJarURL = (JarURLConnection)resource.openConnection(); + if (!resourceJarURL.getJarFileURL().equals(jarURL)) { + return null; + } + } else { + return null; + } + } + + return resource; + } + /** * This class is used only by native JVM code at CDS dump time for loading * "unregistered classes", which are archived classes that are intended to diff --git a/src/java.base/share/classes/sun/security/ec/ECDSASignature.java b/src/java.base/share/classes/sun/security/ec/ECDSASignature.java index 029affbac3d4..a3226889a90d 100644 --- a/src/java.base/share/classes/sun/security/ec/ECDSASignature.java +++ b/src/java.base/share/classes/sun/security/ec/ECDSASignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,7 +157,9 @@ protected void engineUpdate(byte b) throws SignatureException { @Override protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { - if (offset >= precomputedDigest.length) { + // Check capacity. If precomputedDigest is already full, this + // condition effectively becomes 'len > -1' and will always be true + if (len > precomputedDigest.length - offset) { offset = RAW_ECDSA_MAX + 1; return; } @@ -172,7 +174,7 @@ protected void engineUpdate(ByteBuffer byteBuffer) { if (len <= 0) { return; } - if (len >= precomputedDigest.length - offset) { + if (len > precomputedDigest.length - offset) { offset = RAW_ECDSA_MAX + 1; return; } diff --git a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index c7240b54ebdc..7c9d306b78ec 100644 --- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -83,7 +83,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { = "PBEWithHmacSHA256AndAES_256"; private static final String DEFAULT_KEY_PBE_ALGORITHM = "PBEWithHmacSHA256AndAES_256"; - private static final String DEFAULT_MAC_ALGORITHM = "HmacPBESHA256"; + private static final String DEFAULT_MAC_ALGORITHM = "PBEWithHmacSHA256"; private static final int DEFAULT_CERT_PBE_ITERATION_COUNT = 10000; private static final int DEFAULT_KEY_PBE_ITERATION_COUNT = 10000; private static final int DEFAULT_MAC_ITERATION_COUNT = 10000; diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 74797ed663b0..4289254affcf 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -845,7 +845,7 @@ jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ # jdk.crypto.disabledAlgorithms=Cipher.RSA/ECB/PKCS1Padding, MessageDigest.MD2 # jdk.crypto.legacyAlgorithms=Cipher.RSA/ECB/PKCS1Padding, MessageDigest.MD2 # -#jdk.crypto.legacyAlgorithms= +jdk.crypto.legacyAlgorithms=Cipher.RSA/ECB/PKCS1Padding #jdk.crypto.disabledAlgorithms= # @@ -1373,8 +1373,8 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep # file. This can be any HmacPBE or PBEWith algorithm defined in # the Mac section of the Java Security Standard Algorithm Names Specification, # for example, HmacPBESHA256 or PBEWithHmacSHA256. When set to "NONE", -# no Mac is generated. The default value is "HmacPBESHA256". -#keystore.pkcs12.macAlgorithm = HmacPBESHA256 +# no Mac is generated. The default value is "PBEWithHmacSHA256". +#keystore.pkcs12.macAlgorithm = PBEWithHmacSHA256 # The iteration count used by the MacData algorithm. This value must be a # positive integer. The default value is 10000. diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c index 0779294cdae3..ad0994aa3e72 100644 --- a/src/java.base/unix/native/libnio/ch/Net.c +++ b/src/java.base/unix/native/libnio/ch/Net.c @@ -276,8 +276,7 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, */ if (domain == AF_INET6 && ipv4_available()) { int arg = 0; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, - sizeof(int)) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, sizeof(int)) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unable to set IPV6_V6ONLY"); @@ -288,8 +287,7 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, if (reuse) { int arg = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, - sizeof(arg)) < 0) { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, sizeof(arg)) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unable to set SO_REUSEADDR"); @@ -299,10 +297,14 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, } #if defined(__linux__) - /* IPv4 or IPv6 datagram socket: disable IP_MULTICAST_ALL (Linux 2.6.31) */ + /* + * IPv4 or IPv6 datagram socket: disable IP_MULTICAST_ALL (Linux 2.6.31) + * Not supported by the Linux binary compatibility layer on BSD + */ if (type == SOCK_DGRAM && ipv4_available()) { int arg = 0; - if ((setsockopt(fd, IPPROTO_IP, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0)) { + if ((setsockopt(fd, IPPROTO_IP, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) && + (errno != ENOPROTOOPT)) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unable to set IP_MULTICAST_ALL"); @@ -418,7 +420,6 @@ Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfd } /* ECONNABORTED => restart accept */ } - if (newfd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return IOS_UNAVAILABLE; @@ -427,14 +428,18 @@ Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfd JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); return IOS_THROWN; } - setfdval(env, newfdo, newfd); remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); - CHECK_NULL_RETURN(remote_ia, IOS_THROWN); - + if (remote_ia == NULL) { + close(newfd); + return IOS_THROWN; + } isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port); - CHECK_NULL_RETURN(isa, IOS_THROWN); + if (isa == NULL) { + close(newfd); + return IOS_THROWN; + } (*env)->SetObjectArrayElement(env, isaa, 0, isa); return 1; diff --git a/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c b/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c index c43c3b906952..299ccc461986 100644 --- a/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c +++ b/src/java.base/unix/native/libnio/ch/UnixDomainSockets.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,8 +172,10 @@ Java_sun_nio_ch_UnixDomainSockets_accept0(JNIEnv *env, jclass clazz, jobject fdo setfdval(env, newfdo, newfd); address = sockaddrToUnixAddressBytes(env, &sa, sa_len); - CHECK_NULL_RETURN(address, IOS_THROWN); - + if (address == NULL) { + close(newfd); + return IOS_THROWN; + } (*env)->SetObjectArrayElement(env, array, 0, address); return 1; diff --git a/src/java.base/unix/native/libnio/ch/UnixFileDispatcherImpl.c b/src/java.base/unix/native/libnio/ch/UnixFileDispatcherImpl.c index 0c6328c56905..08321b602e5b 100644 --- a/src/java.base/unix/native/libnio/ch/UnixFileDispatcherImpl.c +++ b/src/java.base/unix/native/libnio/ch/UnixFileDispatcherImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -191,9 +191,9 @@ Java_sun_nio_ch_UnixFileDispatcherImpl_available0(JNIEnv *env, jobject this, job if (fstat(fd, &fbuf) != -1) { int mode = fbuf.st_mode; if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - int n = ioctl(fd, FIONREAD, &n); - if (n >= 0) { - return n; + int available; + if (ioctl(fd, FIONREAD, &available) >= 0) { + return available; } } else if (S_ISREG(mode)) { size = fbuf.st_size; diff --git a/src/java.base/windows/native/libjava/TimeZone_md.c b/src/java.base/windows/native/libjava/TimeZone_md.c index 5adecff50e7c..7b78951793c1 100644 --- a/src/java.base/windows/native/libjava/TimeZone_md.c +++ b/src/java.base/windows/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,6 +327,7 @@ static int getWinTimeZone(char *winZoneName, size_t winZoneNameBufSize) if (ret != ERROR_SUCCESS) { goto err; } + RegCloseKey(hSubKey); break; } @@ -363,6 +364,7 @@ static int getWinTimeZone(char *winZoneName, size_t winZoneNameBufSize) * found matched record, terminate search */ strcpy(winZoneName, subKeyName); + RegCloseKey(hSubKey); break; } out: diff --git a/src/java.base/windows/native/libjli/java_md.c b/src/java.base/windows/native/libjli/java_md.c index 4382eceed7e9..4b3813f8c0f6 100644 --- a/src/java.base/windows/native/libjli/java_md.c +++ b/src/java.base/windows/native/libjli/java_md.c @@ -164,8 +164,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv, } char *jvmtype; - int i = 0; - char** argv = *pargv; /* Find out where the JDK is that we will be using. */ if (!GetJDKInstallRoot(jdkroot, so_jdkroot)) { @@ -197,8 +195,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv, /* Check if we need preload AWT */ #ifdef ENABLE_AWT_PRELOAD - argv = *pargv; - for (i = 0; i < *pargc ; i++) { + char** argv = *pargv; + for (int i = 0; i < *pargc ; i++) { /* Tests the "turn on" parameter only if not set yet. */ if (awtPreloadD3D < 0) { if (GetBoolParamValue(PARAM_PRELOAD_D3D, argv[i]) == 1) { diff --git a/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c index ef5c3e079295..635a5ccd818a 100644 --- a/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c +++ b/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -435,32 +435,36 @@ Java_sun_nio_ch_FileDispatcherImpl_isOther0(JNIEnv *env, jobject this, jobject f HANDLE handle = (HANDLE)(handleval(env, fdo)); BY_HANDLE_FILE_INFORMATION finfo; - if (!GetFileInformationByHandle(handle, &finfo)) + if (!GetFileInformationByHandle(handle, &finfo)) { JNU_ThrowIOExceptionWithLastError(env, "isOther failed"); - DWORD fattr = finfo.dwFileAttributes; + return JNI_FALSE; + } + DWORD fattr = finfo.dwFileAttributes; if ((fattr & FILE_ATTRIBUTE_DEVICE) != 0) return (jboolean)JNI_TRUE; if ((fattr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; void* lpOutBuffer = (void*)malloc(size*sizeof(char)); - if (lpOutBuffer == NULL) + if (lpOutBuffer == NULL) { JNU_ThrowOutOfMemoryError(env, "isOther failed"); + return JNI_FALSE; + } DWORD bytesReturned; if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, lpOutBuffer, (DWORD)size, &bytesReturned, NULL)) { free(lpOutBuffer); JNU_ThrowIOExceptionWithLastError(env, "isOther failed"); + return JNI_FALSE; } ULONG reparseTag = (*((PULONG)lpOutBuffer)); free(lpOutBuffer); - return reparseTag == IO_REPARSE_TAG_SYMLINK ? - (jboolean)JNI_FALSE : (jboolean)JNI_TRUE; + return reparseTag == IO_REPARSE_TAG_SYMLINK ? JNI_FALSE : JNI_TRUE; } - return (jboolean)JNI_FALSE; + return JNI_FALSE; } JNIEXPORT jint JNICALL diff --git a/src/java.base/windows/native/libnio/ch/Net.c b/src/java.base/windows/native/libnio/ch/Net.c index adfd67b50171..aff73441cfd7 100644 --- a/src/java.base/windows/native/libnio/ch/Net.c +++ b/src/java.base/windows/native/libnio/ch/Net.c @@ -158,25 +158,19 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, int domain = (preferIPv6) ? AF_INET6 : AF_INET; s = socket(domain, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); - if (s != INVALID_SOCKET) { - SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); - - /* Attempt to disable IPV6_V6ONLY to ensure dual-socket support; ignore errors */ - if (domain == AF_INET6) { - int opt = 0; - setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - (const char *)&opt, sizeof(opt)); - } - - /* Disable WSAECONNRESET errors for initially unconnected UDP sockets */ - if (!stream) { - setConnectionReset(s, FALSE); - } - - } else { + if (s == INVALID_SOCKET) { NET_ThrowNew(env, WSAGetLastError(), "socket"); + return IOS_THROWN; + } + SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); + + /* Attempt to disable IPV6_V6ONLY to ensure dual-socket support; ignore errors */ + if (domain == AF_INET6 && ipv4_available()) { + int opt = 0; + setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&opt, sizeof(opt)); } + /* Enable SIO_LOOPBACK_FAST_PATH on TCP sockets if possible */ if (stream && fastLoopback) { static int loopback_available = 1; if (loopback_available) { @@ -186,11 +180,18 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, loopback_available = 0; } else { NET_ThrowNew(env, rv, "fastLoopback"); + closesocket(s); + return IOS_THROWN; } } } } + /* Disable WSAECONNRESET errors for initially unconnected UDP sockets */ + if (!stream) { + setConnectionReset(s, FALSE); + } + return (jint)s; } @@ -290,15 +291,19 @@ Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfd JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); return IOS_THROWN; } - SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); setfdval(env, newfdo, newfd); remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); - CHECK_NULL_RETURN(remote_ia, IOS_THROWN); - + if (remote_ia == NULL) { + closesocket(newfd); + return IOS_THROWN; + } isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port); - CHECK_NULL_RETURN(isa, IOS_THROWN); + if (isa == NULL) { + closesocket(newfd); + return IOS_THROWN; + } (*env)->SetObjectArrayElement(env, isaa, 0, isa); return 1; diff --git a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c index e29d8e28efc7..b323ebbcc7b8 100644 --- a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c +++ b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,7 +237,10 @@ Java_sun_nio_ch_UnixDomainSockets_accept0(JNIEnv *env, jclass clazz, jobject fdo setfdval(env, newfdo, newfd); address = sockaddrToUnixAddressBytes(env, &sa, sa_len); - CHECK_NULL_RETURN(address, IOS_THROWN); + if (address == NULL) { + closesocket(newfd); + return IOS_THROWN; + } (*env)->SetObjectArrayElement(env, array, 0, address); return 1; diff --git a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c index 07452cbef0a0..87beaf4fc666 100644 --- a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c +++ b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c @@ -901,8 +901,8 @@ Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env, { WCHAR domain[255]; WCHAR name[255]; - DWORD domainLen = sizeof(domain); - DWORD nameLen = sizeof(name); + DWORD domainLen = (DWORD)(sizeof(domain) / sizeof(domain[0])); + DWORD nameLen = (DWORD)(sizeof(name) / sizeof(name[0])); SID_NAME_USE use; PSID sid = jlong_to_ptr(address); jstring s; @@ -932,7 +932,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env, LPCWSTR accountName = jlong_to_ptr(nameAddress); PSID sid = jlong_to_ptr(sidAddress); WCHAR domain[255]; - DWORD domainLen = sizeof(domain); + DWORD domainLen = (DWORD)(sizeof(domain) / sizeof(domain[0])); SID_NAME_USE use; if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid, diff --git a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c index 37d8d943a9aa..a4dfea1d1bc3 100644 --- a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c +++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,8 +120,6 @@ INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT32 timestamp) { int err; int status; - int data1; - int data2; char buffer[3]; TRACE2("> MIDI_OUT_SendShortMessage() %x, time: %u\n", packedMsg, (unsigned int) timestamp); diff --git a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c index 332abb58b6fb..d77c30840c42 100644 --- a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c +++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -412,13 +412,14 @@ int setSWParams(AlsaPcmInfo* info) { return TRUE; } +#ifdef USE_TRACE static snd_output_t* ALSA_OUTPUT = NULL; +#endif void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int encoding, float sampleRate, int sampleSizeInBits, int frameSize, int channels, int isSigned, int isBigEndian, int bufferSizeInBytes) { - snd_pcm_format_mask_t* formatMask; snd_pcm_format_t format; int dir; int ret = 0; @@ -888,7 +889,6 @@ INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) { if (!info->isFlushed && state != SND_PCM_STATE_XRUN) { #ifdef GET_POSITION_METHOD2 - snd_timestamp_t* ts; snd_pcm_uframes_t framesAvail; // note: slight race condition if this is called simultaneously from 2 threads diff --git a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c index c57b2bd3cf50..f14742cb3977 100644 --- a/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c +++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -532,7 +532,6 @@ INT32 PORT_GetIntValue(void* controlIDV) { void PORT_SetIntValue(void* controlIDV, INT32 value) { PortControl* portControl = (PortControl*) controlIDV; - snd_mixer_selem_channel_id_t channel; if (portControl != NULL) { if (portControl->controlType == CONTROL_TYPE_MUTE) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java index ba58f505b311..9d6eaadec519 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,25 +33,30 @@ import javax.swing.plaf.basic.BasicEditorPaneUI; import javax.swing.text.*; +import sun.swing.SwingAccessor; + public final class AquaEditorPaneUI extends BasicEditorPaneUI { public static ComponentUI createUI(final JComponent c){ return new AquaEditorPaneUI(); } - boolean oldDragState = false; + private boolean oldDragState; + @Override protected void installDefaults(){ + oldDragState = getComponent().getDragEnabled(); super.installDefaults(); - if(!GraphicsEnvironment.isHeadless()){ - oldDragState = getComponent().getDragEnabled(); - getComponent().setDragEnabled(true); + if (!GraphicsEnvironment.isHeadless()) { + LookAndFeel.installProperty(getComponent(), "dragEnabled", true); } } @Override - protected void uninstallDefaults(){ - if(!GraphicsEnvironment.isHeadless()){ - getComponent().setDragEnabled(oldDragState); + protected void uninstallDefaults() { + if (!SwingAccessor.getJTextComponentAccessor() + .isDragEnabledSet(getComponent())) { + LookAndFeel.installProperty(getComponent(), "dragEnabled", + oldDragState); } super.uninstallDefaults(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java index d968412da761..8aa7f9c008cd 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import javax.swing.plaf.basic.BasicTextAreaUI; import javax.swing.text.*; +import sun.swing.SwingAccessor; + public final class AquaTextAreaUI extends BasicTextAreaUI { public static ComponentUI createUI(final JComponent c) { return new AquaTextAreaUI(); @@ -67,20 +69,23 @@ protected void uninstallListeners() { super.uninstallListeners(); } - boolean oldDragState = false; + private boolean oldDragState; + @Override - protected void installDefaults() { + protected void installDefaults(){ + oldDragState = getComponent().getDragEnabled(); + super.installDefaults(); if (!GraphicsEnvironment.isHeadless()) { - oldDragState = getComponent().getDragEnabled(); - getComponent().setDragEnabled(true); + LookAndFeel.installProperty(getComponent(), "dragEnabled", true); } - super.installDefaults(); } @Override protected void uninstallDefaults() { - if (!GraphicsEnvironment.isHeadless()) { - getComponent().setDragEnabled(oldDragState); + if (!SwingAccessor.getJTextComponentAccessor() + .isDragEnabledSet(getComponent())) { + LookAndFeel.installProperty(getComponent(), "dragEnabled", + oldDragState); } super.uninstallDefaults(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldUI.java index e3287ccbce93..d1b09c459e03 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import javax.swing.plaf.basic.BasicTextFieldUI; import javax.swing.text.*; +import sun.swing.SwingAccessor; import com.apple.laf.AquaUtils.JComponentPainter; public class AquaTextFieldUI extends BasicTextFieldUI { @@ -68,24 +69,25 @@ protected void uninstallListeners() { super.uninstallListeners(); } - boolean oldDragState = false; + private boolean oldDragState; + @Override - protected void installDefaults() { + protected void installDefaults(){ + oldDragState = getComponent().getDragEnabled(); + super.installDefaults(); if (!GraphicsEnvironment.isHeadless()) { - oldDragState = getComponent().getDragEnabled(); - getComponent().setDragEnabled(true); + LookAndFeel.installProperty(getComponent(), "dragEnabled", true); } - - super.installDefaults(); } @Override protected void uninstallDefaults() { - super.uninstallDefaults(); - - if (!GraphicsEnvironment.isHeadless()) { - getComponent().setDragEnabled(oldDragState); + if (!SwingAccessor.getJTextComponentAccessor() + .isDragEnabledSet(getComponent())) { + LookAndFeel.installProperty(getComponent(), "dragEnabled", + oldDragState); } + super.uninstallDefaults(); } // Install a default keypress action which handles Cmd and Option keys diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java index 571cbf6369a2..d8d8d5520195 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import javax.swing.plaf.basic.BasicTextPaneUI; import javax.swing.text.*; +import sun.swing.SwingAccessor; + //[3663467] moved it to sublcass from BasicEditorPaneUI to BasicTextPaneUI. (vm) public final class AquaTextPaneUI extends BasicTextPaneUI { public static ComponentUI createUI(final JComponent c) { @@ -63,25 +65,28 @@ protected void uninstallListeners() { super.uninstallListeners(); } - boolean oldDragState = false; + private boolean oldDragState; + @Override - protected void installDefaults() { - final JTextComponent c = getComponent(); + protected void installDefaults(){ + oldDragState = getComponent().getDragEnabled(); + super.installDefaults(); if (!GraphicsEnvironment.isHeadless()) { - oldDragState = c.getDragEnabled(); - c.setDragEnabled(true); + LookAndFeel.installProperty(getComponent(), "dragEnabled", true); } - super.installDefaults(); } @Override protected void uninstallDefaults() { - if (!GraphicsEnvironment.isHeadless()) { - getComponent().setDragEnabled(oldDragState); + if (!SwingAccessor.getJTextComponentAccessor() + .isDragEnabledSet(getComponent())) { + LookAndFeel.installProperty(getComponent(), "dragEnabled", + oldDragState); } super.uninstallDefaults(); } + // Install a default keypress action which handles Cmd and Option keys // properly @Override diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiUtils.c b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiUtils.c index 09aeb863496b..00b450bd9871 100644 --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiUtils.c +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiUtils.c @@ -542,8 +542,9 @@ INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle) { INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) { +#ifdef USE_ERROR OSStatus err = noErr; - +#endif if (!handle || !handle->h.deviceHandle) { ERROR0("ERROR: MIDI_Utils_StartDevice: handle or native is NULL\n"); return MIDI_INVALID_HANDLE; @@ -565,10 +566,16 @@ INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) { // Similarly, handle->h.queue is used in the CoreMDID's callback // to dispatch the incoming messages to the appropriate queue. // - err = MIDIPortConnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle), (void*) handle); +#ifdef USE_ERROR + err = +#endif + MIDIPortConnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle), (void*) handle); } else if (handle->direction == MIDI_OUT) { // Unschedules previous-sent packets. - err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle); +#ifdef USE_ERROR + err = +#endif + MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle); } MIDI_CHECK_ERROR; @@ -578,8 +585,9 @@ INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) { INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle) { +#ifdef USE_ERROR OSStatus err = noErr; - +#endif if (!handle || !handle->h.deviceHandle) { ERROR0("ERROR: MIDI_Utils_StopDevice: handle or native handle is NULL\n"); return MIDI_INVALID_HANDLE; @@ -590,10 +598,16 @@ INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle) { handle->isStarted = FALSE; if (handle->direction == MIDI_IN) { - err = MIDIPortDisconnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle)); +#ifdef USE_ERROR + err = +#endif + MIDIPortDisconnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle)); } else if (handle->direction == MIDI_OUT) { // Unschedules previously-sent packets. - err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle); +#ifdef USE_ERROR + err = +#endif + MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle); } MIDI_CHECK_ERROR; diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp index bae16cb0a9c0..5364978a257c 100644 --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp @@ -764,10 +764,16 @@ static OSStatus InputCallback(void *inRefCon, } device->lastWrittenSampleTime = sampleTime + inNumberFrames; - int bytesWritten = device->resampler->Process(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, &device->ringBuffer); +#ifdef USE_TRACE + int bytesWritten = +#endif + device->resampler->Process(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, &device->ringBuffer); TRACE2("<ringBuffer.Write(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, false); +#ifdef USE_TRACE + int bytesWritten = +#endif + device->ringBuffer.Write(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, false); TRACE2("< 0); HKEY hRootKey = HKEY_CURRENT_USER; HKEY hKey; - LONG lRet = ::RegOpenKeyExA(hRootKey, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey); + LONG lRet = ::RegOpenKeyExA(hRootKey, lpszSubKey, 0, KEY_READ, &hKey); if (lRet != ERROR_SUCCESS) { m_fEUDCSubKeyExist = FALSE; return; // no EUDC font @@ -1802,10 +1803,13 @@ void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName) BOOL fUseDefault = FALSE; if (lStatus != ERROR_SUCCESS){ // try System default EUDC font - if (m_fTTEUDCFileExist == FALSE) + if (m_fTTEUDCFileExist == FALSE) { + RegCloseKey(hKey); return; + } if (wcslen(m_szDefaultEUDCFile) > 0) { StringCchCopy(lpszFileName, cchFileName, m_szDefaultEUDCFile); + RegCloseKey(hKey); return; } char szDefault[] = "SystemDefaultEUDCFont"; @@ -1816,6 +1820,7 @@ void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName) m_fTTEUDCFileExist = FALSE; // This font is associated with no EUDC font // and there is no system default EUDC font + RegCloseKey(hKey); return; } } @@ -1824,6 +1829,7 @@ void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName) // This font is associated with no EUDC font // and the system default EUDC font is not TrueType m_fTTEUDCFileExist = FALSE; + RegCloseKey(hKey); return; } @@ -1832,6 +1838,7 @@ void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName) (LPCSTR)szFileName, -1, lpszFileName, cchFileName) != 0); if (fUseDefault) StringCchCopy(m_szDefaultEUDCFile, _MAX_PATH, lpszFileName); + RegCloseKey(hKey); } void CCombinedSegTable::Create(LPCWSTR name) diff --git a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c index 2f700c00dafb..4e26ade6c43d 100644 --- a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -577,7 +577,6 @@ SplashGetScaledImageName(const char* jarName, const char* fileName, { float dpiScaleX = -1.0f; float dpiScaleY = -1.0f; - FILE *fp = NULL; *scaleFactor = 1.0; GetScreenDpi(getPrimaryMonitor(), &dpiScaleX, &dpiScaleY); *scaleFactor = dpiScaleX > 0 ? dpiScaleX / 96 : *scaleFactor; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java b/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java index e1725aa92d59..4e6b6b11d761 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java @@ -161,12 +161,17 @@ HttpConnection getConnection(boolean secure, InetSocketAddress addr, InetSocketAddress proxy) { if (stopped) return null; + List purgedConnections; + HttpConnection acquiredConnection; stateLock.lock(); try { - return getConnection0(secure, addr, proxy); + purgedConnections = purgeExpiredConnections(timeSource.instant()); + acquiredConnection = getConnection0(secure, addr, proxy); } finally { stateLock.unlock(); } + purgedConnections.forEach(this::close); + return acquiredConnection; } private HttpConnection getConnection0(boolean secure, @@ -319,16 +324,7 @@ long purgeExpiredConnectionsAndReturnNextDeadline(Deadline now) { List closelist; stateLock.lock(); try { - closelist = expiryList.purgeUntil(now); - for (HttpConnection c : closelist) { - if (c instanceof PlainHttpConnection) { - boolean wasPresent = removeFromPool(c, plainPool); - assert wasPresent; - } else { - boolean wasPresent = removeFromPool(c, sslPool); - assert wasPresent; - } - } + closelist = purgeExpiredConnections(now); nextPurge = now.until( expiryList.nextExpiryDeadline().orElse(now), ChronoUnit.MILLIS); @@ -339,6 +335,16 @@ long purgeExpiredConnectionsAndReturnNextDeadline(Deadline now) { return nextPurge; } + private List purgeExpiredConnections(Deadline now) { + assert stateLock.isHeldByCurrentThread(); + var closelist = expiryList.purgeUntil(now); + for (HttpConnection c : closelist) { + var wasPresent = removeFromPool(c, c instanceof PlainHttpConnection ? plainPool : sslPool); + assert wasPresent; + } + return closelist; + } + private void close(HttpConnection c) { try { c.close(); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index c113672f8d80..44b81e24c1c4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -68,6 +68,7 @@ import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.SequentialScheduler; +import jdk.internal.net.http.common.TimeSource; import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.common.ValidatingHeadersConsumer; import jdk.internal.net.http.common.ValidatingHeadersConsumer.Context; @@ -222,18 +223,35 @@ final class IdleConnectionTimeoutEvent extends TimeoutEvent { */ @Override public void handle() { - // first check if the connection is still idle. - // must be done with the "stateLock" held, to allow for synchronizing actions like - // closing the connection and checking out from connection pool (which too is expected - // to use this same lock) stateLock.lock(); try { + + // Are we still the effective idle timeout handler? If not, we're done. + if (idleConnectionTimeoutEvent != this) { + if (debug.on()) { + debug.log("Idle timeout event is found obsolete, skipping it"); + } + return; + } + if (cancelled) { if (debug.on()) { - debug.log("Idle timeout event already cancelled, not initiating idle connection close"); + debug.log("Idle timeout event is found cancelled, skipping it"); } return; } + + if (!isIdle()) { + if (debug.on()) { + debug.log("Idle timeout event found the connection in-use, skipping the event"); + } + // When the active/reserved stream later closes, it won't + // arm a new idle timer upon seeing this one, which is + // already fired. Hence, detach this event. + idleConnectionTimeoutEvent = null; + return; + } + // the connection has been idle long enough, we now // mark a state indicating that the connection is chosen // for idle termination and should not be handed out (from the pool) @@ -653,12 +671,21 @@ void abandonStream() { final boolean shouldClose() { stateLock.lock(); try { - return finalStream() && streams.isEmpty() && numReservedClientStreams == 0; + return finalStream() && isIdle(); } finally { stateLock.unlock(); } } + private boolean isIdle() { + assert stateLock.isHeldByCurrentThread(); + // There should not be any server reserved streams if there is no client + // streams for HTTP/2, because push promises are supposed to be created + // while the main response stream is still open. Hence, we don't do a + // `numReservedServerStreams == 0` check. + return streams.isEmpty() && numReservedClientStreams == 0; + } + /** * Throws an IOException if h2 was not negotiated */ @@ -1551,6 +1578,17 @@ boolean tryReserveForPoolCheckout() { // must be done with "stateLock" held to co-ordinate idle connection management stateLock.lock(); try { + + // Idle connection timeout processing might be delayed when this + // connection checkout request has arrived. Hence, first check for + // the timeout. + var timedOut = idleConnectionTimeoutEvent != null && + !idleConnectionTimeoutEvent.deadline().isAfter(TimeSource.now()); + if (timedOut && isIdle()) { + setFinalStream(); + return false; + } + cancelIdleCloseEvent(); // consider the reservation successful only if the connection is open and // hasn't been chosen for idle termination diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http3Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http3Connection.java index 6bf1b9184f86..024de6bd49b3 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http3Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http3Connection.java @@ -52,6 +52,7 @@ import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; +import jdk.internal.net.http.common.TimeSource; import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.http3.ConnectionSettings; import jdk.internal.net.http.http3.Http3Error; @@ -725,12 +726,17 @@ public String toString() { private boolean finalStreamClosed() { lock(); try { - return this.finalStream && this.exchangeStreams.isEmpty() && this.reservedStreamCount.get() == 0; + return this.finalStream && isIdle(); } finally { unlock(); } } + private boolean isIdle() { + assert lock.isHeldByCurrentThread(); + return exchangeStreams.isEmpty() && reservedStreamCount.get() == 0; + } + /** * Called by the {@link Http3ExchangeImpl} when the exchange is closed. * @@ -894,6 +900,18 @@ boolean tryReserveForPoolCheckout() { // must be done with "stateLock" held to co-ordinate idle connection management lock(); try { + + // Idle connection timeout processing might be delayed when this + // connection checkout request has arrived. Hence, first check for + // the timeout. + var idleConnectionTimeoutEventCopy = idleConnectionTimeoutEvent; + var timedOut = idleConnectionTimeoutEventCopy != null && + !idleConnectionTimeoutEventCopy.deadline().isAfter(TimeSource.now()); + if (timedOut && isIdle()) { + setFinalStream(); + return false; + } + cancelIdleShutdownEvent(); // co-ordinate with the QUIC connection to prevent it from silently terminating // a potentially idle transport @@ -981,9 +999,40 @@ public void handle() { boolean okToIdleTimeout; lock(); try { - if (cancelled || idleShutDownInitiated) { + + // Are we still the effective idle timeout handler? If not, we're done. + if (idleConnectionTimeoutEvent != this) { + if (debug.on()) { + debug.log("Idle timeout event is found obsolete, skipping it"); + } return; } + + if (cancelled) { + if (debug.on()) { + debug.log("Idle timeout event is found cancelled, skipping it"); + } + return; + } + + if (idleShutDownInitiated) { + if (debug.on()) { + debug.log("Idle timeout event found the shutdown initiated, skipping the event"); + } + return; + } + + if (!isIdle()) { + if (debug.on()) { + debug.log("Idle timeout event found the connection in-use, skipping the event"); + } + // When the active/reserved stream later closes, it won't + // arm a new idle timer upon seeing this one, which is + // already fired. Hence, detach this event. + idleConnectionTimeoutEvent = null; + return; + } + idleShutDownInitiated = true; if (debug.on()) { debug.log("H3 idle shutdown initiated"); diff --git a/src/java.se/share/data/jdwp/jdwp.spec b/src/java.se/share/data/jdwp/jdwp.spec index c8cdb99d4a69..f8973fb1406d 100644 --- a/src/java.se/share/data/jdwp/jdwp.spec +++ b/src/java.se/share/data/jdwp/jdwp.spec @@ -731,6 +731,11 @@ JDWP "Java(tm) Debug Wire Protocol" "or one of its superclasses, superinterfaces, or implemented interfaces. " "Access control is not enforced; for example, the values of private " "fields can be obtained." + "

" + "When preview features are enabled in the target VM, " + "this command does not prevent a " + "strictly-initialized fieldPREVIEW " + "from being read before it has been initialized." (Out (referenceType refType "The reference type ID.") (Repeat fields "The number of values to get" @@ -1090,7 +1095,8 @@ JDWP "Java(tm) Debug Wire Protocol" "Each field must be member of the class type " "or one of its superclasses, superinterfaces, or implemented interfaces. " "Access control is not enforced; for example, the values of private " - "fields can be set. Final fields cannot be set." + "fields can be set. Setting a final static field is permitted but may " + "result in an unexpected exception or a fatal crash. " "For primitive values, the value's type must match the " "field's type exactly. For object values, there must exist a " "widening reference conversion from the value's type to the @@ -1559,6 +1565,11 @@ JDWP "Java(tm) Debug Wire Protocol" "or one of its superclasses, superinterfaces, or implemented interfaces. " "Access control is not enforced; for example, the values of private " "fields can be obtained." + "

" + "When preview features are enabled in the target VM, " + "this command does not prevent a " + "strictly-initialized fieldPREVIEW " + "from being read before it has been initialized." (Out (object object "The object ID") (Repeat fields "The number of values to get" @@ -1586,7 +1597,8 @@ JDWP "Java(tm) Debug Wire Protocol" "Each field must be member of the object's type " "or one of its superclasses, superinterfaces, or implemented interfaces. " "Access control is not enforced; for example, the values of private " - "fields can be set. " + "fields can be set. Setting a final instance field is permitted but may " + "result in an unexpected exception or a fatal crash. " "For primitive values, the value's type must match the " "field's type exactly. For object values, there must be a " "widening reference conversion from the value's type to the @@ -2129,8 +2141,9 @@ JDWP "Java(tm) Debug Wire Protocol" "language method. Forcing return on a thread with only one " "frame on the stack causes the thread to exit when resumed. " "

" - "When preview features are enabled, the method can not be the " - "constructor of a value class." + "When preview features are enabled in the target VM, " + "the method can not be the constructor of a " + "value classPREVIEW." "

" "For void methods, the value must be a void value. " "For methods that return primitive values, the value's type must " @@ -2605,8 +2618,10 @@ JDWP "Java(tm) Debug Wire Protocol" "index can be determined for method arguments from the method " "signature without access to the local variable table information.) " "

" - "When preview features are enabled, if the local variable is the 'this' " - "object and represents a value object under construction, the value returned " + "When preview features are enabled in the target VM, " + "if the local variable is the 'this' object and represents a " + "value objectPREVIEW " + "under construction, the value returned " "will be for a snapshot of the value object, not a reference to the actual " "value object under construction. Therefore the value returned will not reflect " "changes to the value object that happen later on during construction." @@ -2683,7 +2698,9 @@ JDWP "Java(tm) Debug Wire Protocol" "If the frame's method is static or native, the reply " "will contain the null object reference. " "

" - "When preview features are enabled and 'this' represents a value object + "When preview features are enabled on the target VM, " + "if 'this' represents a " + "value objectPREVIEW " "under construction, the value returned will be for a snapshot of the " "value object, not a reference to the actual value object under " "construction. Therefore the value returned will not reflect " diff --git a/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp b/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp index 797e6fc4762f..c802c1146b80 100644 --- a/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp +++ b/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp @@ -557,7 +557,7 @@ void Jaccesswalker::addComponentNodes(long vmID, AccessibleContext context, tvis.hInsertAfter = TVI_LAST; // make tree in order given tvis.item = tvi; - HTREEITEM treeNodeItem = TreeView_InsertItem(treeWnd, &tvis); + [[maybe_unused]] HTREEITEM treeNodeItem = TreeView_InsertItem(treeWnd, &tvis); } } diff --git a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeJavaVMInstance.cpp b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeJavaVMInstance.cpp index b34231af83c3..e301185c008e 100644 --- a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeJavaVMInstance.cpp +++ b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeJavaVMInstance.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -268,7 +268,7 @@ AccessBridgeJavaVMInstance::sendMemoryPackage(char *buffer, long bufsize) { DEBUG_CODE(PackageType *type = (PackageType *) memoryMappedView); DEBUG_CODE(if (*type == cGetAccessibleTextItemsPackage) {) DEBUG_CODE(AppendToCallInfo(" 'memoryMappedView' now contains:")); - DEBUG_CODE(GetAccessibleTextItemsPackage *pkg = (GetAccessibleTextItemsPackage *) (buffer + sizeof(PackageType))); + DEBUG_CODE([[maybe_unused]] GetAccessibleTextItemsPackage *pkg = (GetAccessibleTextItemsPackage *) (buffer + sizeof(PackageType))); DEBUG_CODE(snprintf(outputBuf, sizeof(outputBuf), " PackageType = %X", *type)); DEBUG_CODE(AppendToCallInfo(outputBuf)); DEBUG_CODE(}) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index 3e41ccb5766e..8903088e4b20 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -260,7 +260,7 @@ public Error disabledError(JavaFileObject classfile, int majorVersion) { * @return true iff sym has been declared using a preview language feature */ public boolean declaredUsingPreviewFeature(Symbol sym) { - return false; + return sym.isValueClass(); } public void checkSourceLevel(DiagnosticPosition pos, Feature feature) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index e6c28d3bf197..5aed62995e64 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -770,7 +770,6 @@ protected void attribSuperTypes(Env env, Env baseEnv) true, false, false) : syms.objectType; } - ct.supertype_field = modelMissingTypes(baseEnv, supertype, extending, false); // Determine interfaces. ListBuffer interfaces = new ListBuffer<>(); @@ -789,6 +788,7 @@ protected void attribSuperTypes(Env env, Env baseEnv) } } + ct.supertype_field = modelMissingTypes(baseEnv, supertype, extending, false); if ((sym.flags_field & ANNOTATION) != 0) { ct.interfaces_field = List.of(syms.annotationType); ct.all_interfaces_field = ct.interfaces_field; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index afd3fed8757e..39c0339ac287 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1002,9 +1002,6 @@ void writeField(VarSymbol v) { Type fldType = v.erasure(types); if (fldType.requiresLoadableDescriptors(v.owner)) { poolWriter.enterLoadableDescriptorsClass(fldType.tsym); - if (preview.isPreview(Source.Feature.VALUE_CLASSES)) { - preview.markUsesPreview(null); - } } int acountIdx = beginAttrs(); int acount = 0; @@ -1035,17 +1032,11 @@ void writeMethod(MethodSymbol m) { for (Type t : mtype.getParameterTypes()) { if (t.requiresLoadableDescriptors(m.owner)) { poolWriter.enterLoadableDescriptorsClass(t.tsym); - if (preview.isPreview(Source.Feature.VALUE_CLASSES)) { - preview.markUsesPreview(null); - } } } Type returnType = mtype.getReturnType(); if (returnType.requiresLoadableDescriptors(m.owner)) { poolWriter.enterLoadableDescriptorsClass(returnType.tsym); - if (preview.isPreview(Source.Feature.VALUE_CLASSES)) { - preview.markUsesPreview(null); - } } int acountIdx = beginAttrs(); int acount = 0; diff --git a/src/jdk.compiler/share/man/javac.md b/src/jdk.compiler/share/man/javac.md index c749ca4da10c..47d0d7f04eee 100644 --- a/src/jdk.compiler/share/man/javac.md +++ b/src/jdk.compiler/share/man/javac.md @@ -139,7 +139,7 @@ file system locations may be directories, JAR files or JMOD files. `@`*filename* : Reads options and file names from a file. To shorten or simplify the `javac` command, you can specify one or more files that contain arguments - to the `javac` command (except [`-J`](#option-J) options). This lets you to create + to the `javac` command (except [`-J`](#option-J) options). This lets you create `javac` commands of any length on any operating system. See [Command-Line Argument Files]. @@ -233,7 +233,7 @@ file system locations may be directories, JAR files or JMOD files. If you are compiling for a release of the platform that supports the Extension Mechanism, then this option specifies the directories that contain the extension classes. - See [Compiling for Other Releases of the Platform]. + See [Compiling for Earlier Releases of the Platform]. **Note:** This can only be used when compiling for releases prior to JDK 9. As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), or @@ -297,7 +297,7 @@ file system locations may be directories, JAR files or JMOD files. `-J`*option* : Passes *option* to the runtime system, where *option* is one of the Java - options described on [java](java.html) command. For example, `-J-Xms48m` + options described for the [java](java.html) command. For example, `-J-Xms48m` sets the startup memory to 48 MB. **Note:** The `CLASSPATH` environment variable, `-classpath` option, `-bootclasspath` @@ -1150,7 +1150,7 @@ This may be useful when performing white-box testing; relying on access to internal API in production code is strongly discouraged. You can patch additional content into any module using the -[`--patch-module`](#option-patch-module) option. See [Patching a Module] for more details. +[`--patch-module`](#option-patch-module) option. See [Patching Modules] for more details. ## Searching for Module, Package and Type Declarations @@ -1234,7 +1234,7 @@ If the module is one of those currently being compiled, the module declaration will be either the file named `module-info.class` in the root of the package hierarchy for the module in the class output directory, or the file named `module-info.java` in one of the locations on the source path -or one the module source path for the module. +or on the module source path for the module. ### Searching for the Declaration of a Type When the Reference is not in a Module @@ -1273,7 +1273,7 @@ readable by the enclosing module. If so, `javac` will simply and directly go to the definition of that module to find the definition of the required type. Unless the module is another of the modules being compiled, `javac` will -only look for compiled class files files. In other words, `javac` will +only look for compiled class files. In other words, `javac` will not look for source files in platform modules or modules on the module path. If the type being referenced is not in some other readable module, @@ -1476,7 +1476,7 @@ specified, then the user class path is used. Processors are located by means of service provider-configuration files named `META-INF/services/javax.annotation.processing.Processor` on the search path. Such files should contain the names of any -annotationation processors to be used, listed one per +annotation processors to be used, listed one per line. Alternatively, processors can be specified explicitly, using the [`-processor`](#option-processor) option. @@ -1651,7 +1651,7 @@ internal and subject to change at any time. > `int divideByZero = 42 / 0;` `empty` -: Warns about empty statements after `if`statements, for example: +: Warns about empty statements after `if` statements, for example: ``` class E { diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.cpp index bb7328379f02..f23ffce9a071 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.cpp +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.cpp @@ -265,14 +265,14 @@ uint32_t DwarfParser::get_decoded_value(unsigned char enc) { // https://gcc.gnu.org/ml/gcc-help/2010-09/msg00166.html #if defined(_LP64) if (size == 8) { - result += _lib->eh_frame.v_addr + static_cast(_buf - _lib->eh_frame.data); + result += _lib->frame.v_addr + static_cast(_buf - _lib->frame.data); size = 4; } else #endif if ((enc & 0x70) == 0x10) { // 0x10 = DW_EH_PE_pcrel - result += _lib->eh_frame.v_addr + static_cast(_buf - _lib->eh_frame.data); + result += _lib->frame.v_addr + static_cast(_buf - _lib->frame.data); } else if (size == 2) { - result = static_cast(result) + _lib->eh_frame.v_addr + static_cast(_buf - _lib->eh_frame.data); + result = static_cast(result) + _lib->frame.v_addr + static_cast(_buf - _lib->frame.data); size = 4; } @@ -319,8 +319,8 @@ unsigned int DwarfParser::get_pc_range() { bool DwarfParser::process_dwarf(const uintptr_t pc) { // https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html - _buf = _lib->eh_frame.data; - unsigned char *end = _lib->eh_frame.data + _lib->eh_frame.size; + _buf = _lib->frame.data; + unsigned char *end = _lib->frame.data + _lib->frame.size; while (_buf <= end) { uint64_t length = get_entry_length(); if (length == 0L) { @@ -331,7 +331,7 @@ bool DwarfParser::process_dwarf(const uintptr_t pc) { uint32_t id = *(reinterpret_cast(_buf)); _buf += 4; if (id != 0) { // FDE - uintptr_t pc_begin = get_decoded_value(_fde_ptr_encoding) + _lib->eh_frame.library_base_addr; + uintptr_t pc_begin = get_decoded_value(_fde_ptr_encoding) + _lib->base; uintptr_t pc_end = pc_begin + get_pc_range(); if ((pc >= pc_begin) && (pc < pc_end)) { diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.hpp b/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.hpp index 38ffaceb687e..110cd91ed4c4 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.hpp +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.hpp @@ -108,7 +108,7 @@ class DwarfParser { } bool is_parseable() { - return _lib->eh_frame.data != NULL; + return _lib->frame.data != NULL; } }; diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c index 815902045cff..cc8f956bb0c1 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c @@ -128,7 +128,7 @@ static void destroy_lib_info(struct ps_prochandle* ph) { if (lib->symtab) { destroy_symtab(lib->symtab); } - free(lib->eh_frame.data); + free(lib->frame.data); free(lib); lib = next; } @@ -231,10 +231,9 @@ bool read_eh_frame(struct ps_prochandle* ph, lib_info* lib) { for (cnt = 0, sh = shbuf; cnt < ehdr.e_shnum; cnt++, sh++) { if (strcmp(".eh_frame", sh->sh_name + strtab) == 0) { - lib->eh_frame.library_base_addr = lib->base; - lib->eh_frame.v_addr = sh->sh_addr; - lib->eh_frame.data = read_section_data(lib->fd, &ehdr, sh); - lib->eh_frame.size = sh->sh_size; + lib->frame.v_addr = sh->sh_addr; + lib->frame.data = read_section_data(lib->fd, &ehdr, sh); + lib->frame.size = sh->sh_size; break; } } @@ -242,7 +241,7 @@ bool read_eh_frame(struct ps_prochandle* ph, lib_info* lib) { free(strtab); free(shbuf); lseek(lib->fd, current_pos, SEEK_SET); - return lib->eh_frame.data != NULL; + return lib->frame.data != NULL; } lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h index d5aa74e73ad7..23d7daea9729 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h @@ -34,13 +34,12 @@ #define BUF_SIZE (PATH_MAX + NAME_MAX + 1) -// .eh_frame data -typedef struct eh_frame_info { - uintptr_t library_base_addr; +// frame data +typedef struct frame_info { uintptr_t v_addr; unsigned char* data; int size; -} eh_frame_info; +} frame_info; // list of shared objects typedef struct lib_info { @@ -49,7 +48,7 @@ typedef struct lib_info { uintptr_t end; uintptr_t exec_start; uintptr_t exec_end; - eh_frame_info eh_frame; + frame_info frame; struct symtab* symtab; int fd; // file descriptor for lib struct lib_info* next; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java index ece221e9ef3d..b9ab97e3cef2 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java @@ -79,6 +79,12 @@ private Address getSenderCFA(DwarfParser senderDwarf, Address senderSP, Address }; } + // In SysV AMD64, SP should be less than sender SP because return address should be + // pushed onto the stack. + protected boolean isValidFrame(Address senderCFA, Address senderFP, Address senderSP) { + return super.isValidFrame(senderCFA, senderFP) && sp().lessThan(senderSP); + } + @Override public CFrame sender(ThreadProxy th, Address senderSP, Address senderFP, Address senderPC) { if (linuxDbg().isSignalTrampoline(pc())) { @@ -124,7 +130,7 @@ public CFrame sender(ThreadProxy th, Address senderSP, Address senderFP, Address try { Address senderCFA = getSenderCFA(senderDwarf, senderSP, senderFP); - return isValidFrame(senderCFA, senderFP) + return isValidFrame(senderCFA, senderFP, senderSP) ? new LinuxAMD64CFrame(linuxDbg(), senderSP, senderFP, senderCFA, senderPC, senderDwarf, fallback) : null; } catch (DebuggerException e) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahFreeSet.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahFreeSet.java index 9ca8e1deb04e..fdd835c14bdd 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahFreeSet.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahFreeSet.java @@ -1,5 +1,5 @@ /* - * * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceStackChunkKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceStackChunkKlass.java index 246208582c12..75344728e814 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceStackChunkKlass.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceStackChunkKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,4 +51,33 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc public InstanceStackChunkKlass(Address addr) { super(addr); } + + @Override + public long getObjectSize(Oop object) { + // Mirrors InstanceStackChunkKlass::oop_size in the VM, in bytes. + long stackSizeInWords = ((IntField) findField("size", "I")).getValue(object); + return instanceSize(stackSizeInWords); + } + + private long instanceSize(long stackSizeInWords) { + long sizeInWords = getSizeHelper() + stackSizeInWords + gcDataSize(stackSizeInWords); + return Oop.alignObjectSize(sizeInWords * VM.getVM().getAddressSize()); + } + + private static long gcDataSize(long stackSizeInWords) { + return bitmapSize(stackSizeInWords); + } + + private static long bitmapSize(long stackSizeInWords) { + long bitsPerWord = VM.getVM().getBytesPerWord() * 8L; + return bitmapSizeInBits(stackSizeInWords) / bitsPerWord; + } + + private static long bitmapSizeInBits(long stackSizeInWords) { + VM vm = VM.getVM(); + // Need one bit per potential narrowOop* or oop* address. + long bitsPerWord = vm.getBytesPerWord() * 8L; + long sizeInBits = stackSizeInWords * (vm.getBytesPerWord() / vm.getHeapOopSize()); + return vm.alignUp(sizeInBits, bitsPerWord); + } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Mark.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Mark.java index 851ec52abf04..3f217edc9835 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Mark.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Mark.java @@ -63,8 +63,8 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc ageMaskInPlace = db.lookupLongConstant("markWord::age_mask_in_place").longValue(); hashMask = db.lookupLongConstant("markWord::hash_mask").longValue(); hashMaskInPlace = db.lookupLongConstant("markWord::hash_mask_in_place").longValue(); - lockedValue = db.lookupLongConstant("markWord::locked_value").longValue(); - unlockedValue = db.lookupLongConstant("markWord::unlocked_value").longValue(); + fastLockedValue = db.lookupLongConstant("markWord::fast_locked_value").longValue(); + neutralValue = db.lookupLongConstant("markWord::lock_neutral_value").longValue(); monitorValue = db.lookupLongConstant("markWord::monitor_value").longValue(); markedValue = db.lookupLongConstant("markWord::marked_value").longValue(); noHash = db.lookupLongConstant("markWord::no_hash").longValue(); @@ -94,8 +94,8 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc private static long hashMask; private static long hashMaskInPlace; - private static long lockedValue; - private static long unlockedValue; + private static long fastLockedValue; + private static long neutralValue; private static long monitorValue; private static long markedValue; @@ -123,11 +123,11 @@ public Address valueAsAddress() { } // lock accessors (note that these assume lock_shift == 0) - public boolean isLocked() { - return (Bits.maskBitsLong(value(), lockMaskInPlace) != unlockedValue); + public boolean isNonNeutral() { + return (Bits.maskBitsLong(value(), lockMaskInPlace) != neutralValue); } - public boolean isUnlocked() { - return (Bits.maskBitsLong(value(), lockMaskInPlace) == unlockedValue); + public boolean isNeutral() { + return (Bits.maskBitsLong(value(), lockMaskInPlace) == neutralValue); } public boolean isMarked() { return (Bits.maskBitsLong(value(), lockMaskInPlace) == markedValue); @@ -141,15 +141,15 @@ public boolean isBeingInflated() { // Should this header be preserved during GC? public boolean mustBePreserved() { - return (!isUnlocked() || !hasNoHash()); + return (isNonNeutral() || !hasNoHash()); } // WARNING: The following routines are used EXCLUSIVELY by // synchronization functions. They are not really gc safe. // They must get updated if markWord layout get changed. - public boolean hasLocker() { - return ((value() & lockMaskInPlace) == lockedValue); + public boolean isFastLocked() { + return ((value() & lockMaskInPlace) == fastLockedValue); } public boolean hasMonitor() { return ((value() & monitorValue) != 0); @@ -168,7 +168,7 @@ public ObjectMonitor monitor() { return null; } public boolean hasDisplacedMarkHelper() { - return ((value() & unlockedValue) == 0); + return ((value() & neutralValue) == 0); } public Mark displacedMarkHelper() { if (Assert.ASSERTS_ENABLED) { @@ -195,13 +195,13 @@ public Klass getKlass() { // Debugging public void printOn(PrintStream tty) { - if (isLocked()) { + if (isNonNeutral()) { tty.print("locked(0x" + Long.toHexString(value()) + ")->"); displacedMarkHelper().printOn(tty); } else { if (Assert.ASSERTS_ENABLED) { - Assert.that(isUnlocked(), "just checking"); + Assert.that(isNeutral(), "just checking"); } tty.print("mark("); tty.print("hash " + Long.toHexString(hash()) + ","); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java index d565a5b0000d..4a42240314a8 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java @@ -129,7 +129,7 @@ public boolean equals(Object obj) { /** Identity hash in the target VM */ public long identityHash() { Mark mark = getMark(); - if (mark.isUnlocked() && (!mark.hasNoHash())) { + if (mark.isNeutral() && (!mark.hasNoHash())) { return (int) mark.hash(); } else if (mark.isMarked()) { return (int) mark.hash(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java index 9c2cef7d73b5..35ed66f14f13 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java @@ -51,7 +51,7 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc public long identityHashValueFor(Oop obj) { Mark mark = obj.getMark(); - if (mark.isUnlocked()) { + if (mark.isNeutral()) { // FIXME: can not generate marks in debugging system return mark.hash(); } else if (mark.hasMonitor()) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index be8651be3ffb..bda32bed969e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -680,10 +680,7 @@ final DoubleVector broadcastTemplate(long e) { final DoubleVector lanewiseTemplate(VectorOperators.Unary op) { if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return unaryMathOp(op); } } @@ -708,10 +705,7 @@ DoubleVector lanewiseTemplate(VectorOperators.Unary op, VectorMask m) { m.check(maskClass, this); if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0, m)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return blend(unaryMathOp(op), m); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java index 18534d91d54c..708ded947d55 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java @@ -766,10 +766,7 @@ final Float16Vector broadcastTemplate(long e) { final Float16Vector lanewiseTemplate(VectorOperators.Unary op) { if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return unaryMathOp(op); } } @@ -794,10 +791,7 @@ Float16Vector lanewiseTemplate(VectorOperators.Unary op, VectorMask m) { m.check(maskClass, this); if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0, m)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return blend(unaryMathOp(op), m); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 929c0a83b55f..775e939de2bf 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -680,10 +680,7 @@ final FloatVector broadcastTemplate(long e) { final FloatVector lanewiseTemplate(VectorOperators.Unary op) { if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return unaryMathOp(op); } } @@ -708,10 +705,7 @@ FloatVector lanewiseTemplate(VectorOperators.Unary op, VectorMask m) { m.check(maskClass, this); if (opKind(op, VO_SPECIAL)) { - if (op == ZOMO) { - return blend(broadcast(-1), compare(NE, 0, m)); - } - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return blend(unaryMathOp(op), m); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index c593f6edfe6c..bfc8ce3dfeaa 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -843,16 +843,16 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp final $abstractvectortype$ lanewiseTemplate(VectorOperators.Unary op) { if (opKind(op, VO_SPECIAL)) { +#if[BITWISE] if (op == ZOMO) { return blend(broadcast(-1), compare(NE, 0)); } -#if[BITWISE] else if (op == NOT) { return broadcast(-1).lanewise(XOR, this); } #end[BITWISE] #if[FP] - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return unaryMathOp(op); } #end[FP] @@ -878,16 +878,16 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp VectorMask<$Boxtype$> m) { m.check(maskClass, this); if (opKind(op, VO_SPECIAL)) { +#if[BITWISE] if (op == ZOMO) { return blend(broadcast(-1), compare(NE, 0, m)); } -#if[BITWISE] else if (op == NOT) { return lanewise(XOR, broadcast(-1), m); } #end[BITWISE] #if[FP] - else if (opKind(op, VO_MATHLIB)) { + if (opKind(op, VO_MATHLIB)) { return blend(unaryMathOp(op), m); } #end[FP] diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java index 33ea1b7ae1f3..079e486bf0ce 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java @@ -52,10 +52,12 @@ * takes ObjectReference as parameter may throw * {@link ObjectCollectedException} if the mirrored object has been * garbage collected. + * *

*
*

Value Objects

- * If preview features are enabled, JDI supports value objects and classes. + * The Java Debug Interface (JDI) supports debugging of programs that use + * {@linkplain Class#isValue() value objects}. * However, the support does in some cases deviate from identity object * support in behavior or expectations as noted below: *

@@ -66,6 +68,7 @@ * be obtained to see the updated state. See {@link StackFrame#thisObject}. *

*
+ * * @author Robert Field * @author Gordon Hirsch * @author James McIlree @@ -102,8 +105,9 @@ public interface ObjectReference extends Value { * the mirrored object's class or a superclass of that class. *
*
- * If preview features are enabled, this method does not prevent a - * strictly-initialized field from being read before it has been initialized. + * This method does not prevent a + * {@linkplain java.lang.reflect.Field#isStrictInit() strictly-initialized field} + * from being read before it has been initialized. *
*
* @@ -121,8 +125,9 @@ public interface ObjectReference extends Value { * the mirrored object's class or a superclass of that class. *
*
- * If preview features are enabled, this method does not prevent a - * strictly-initialized field from being read before it has been initialized. + * This method does not prevent a + * {@linkplain java.lang.reflect.Field#isStrictInit() strictly-initialized field} + * from being read before it has been initialized. *
*
* diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java b/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java index 66664db999d6..a50cf91010e4 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java @@ -521,8 +521,9 @@ default ModuleReference module() { * superinterface, or an implemented interface. *
*
- * If preview features are enabled, this method does not prevent a - * strictly-initialized field from being read before it has been initialized. + * This method does not prevent a + * {@linkplain java.lang.reflect.Field#isStrictInit() strictly-initialized field} + * from being read before it has been initialized. *
*
* @param field the field containing the requested value @@ -540,8 +541,9 @@ default ModuleReference module() { * superinterface, or an implemented interface. *
*
- * If preview features are enabled, this method does not prevent a - * strictly-initialized field from being read before it has been initialized. + * This method does not prevent a + * {@linkplain java.lang.reflect.Field#isStrictInit() strictly-initialized field} + * from being read before it has been initialized. *
*
* diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/StackFrame.java b/src/jdk.jdi/share/classes/com/sun/jdi/StackFrame.java index 570a167038c3..4e2192b6abee 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/StackFrame.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/StackFrame.java @@ -96,14 +96,18 @@ public interface StackFrame extends Mirror, Locatable { * Returns the value of 'this' for the current frame. * The {@link ObjectReference} for 'this' is only available for * non-native instance methods. - *

- * If 'this' is a {@linkplain - * ObjectReference##valueObjects value objectPREVIEW} + * + *

+ *
+ * If 'this' is a + * {@linkplain ObjectReference##valueObjects value objectPREVIEW} * under construction, the returned {@code ObjectReference} will refer to a * snapshot of the value object, not a reference * to the actual value object under construction. Consequently, the returned * {@code ObjectReference} will not reflect changes to the value object that * happen later during construction. + *
+ *
* * @return an {@link ObjectReference}, or null if the frame represents * a native or static method. diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/Value.java b/src/jdk.jdi/share/classes/com/sun/jdi/Value.java index 19a0c98d1691..96fb1aeb46a5 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/Value.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/Value.java @@ -31,14 +31,14 @@ * The mirror for a value in the target VM. * This interface is the root of a * value hierarchy encompassing primitive values and object values. + * *
*
- * When preview features are enabled, JDI supports value classes. A "value class" - * as supported in the Java language is not related to the JDI Value interface. - * A "value class" is a class declared with the "value" modifier. The JDI - * Value interface is used by JDI to mirror a value in the debuggee VM. For more - * information on value classes, see Section {@jls value-objects-8.1.1.5 Value Classes} - * of The Java Language Specification. + * The Java Debug Interface (JDI) supports debugging of programs that use + * {@linkplain Class#isValue() value objects}. A value object is an instance of a + * value class, declared with the value modifier. The JDI + * {@code com.sun.jdi.Value} interface is used to mirror a value in the target VM. + * That value may be a value object or an identity object. *
*
*

diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 1fbe07803c75..4381da513def 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,10 +34,10 @@ public final class ChunkHeader { public static final long HEADER_SIZE = 68; - static final byte UPDATING_CHUNK_HEADER = (byte) 255; + public static final byte UPDATING_CHUNK_HEADER = (byte) 255; public static final long CHUNK_SIZE_POSITION = 8; static final long DURATION_NANOS_POSITION = 40; - static final long FILE_STATE_POSITION = 64; + public static final long FILE_STATE_POSITION = 64; static final long FLAG_BYTE_POSITION = 67; static final long METADATA_TYPE_ID = 0; static final byte[] FILE_MAGIC = { 'F', 'L', 'R', '\0' }; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java index 001bd39896e3..03aa9166ed58 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java @@ -98,7 +98,7 @@ public RecordingInput(File f) throws IOException { this(f, DEFAULT_BLOCK_SIZE); } - void positionPhysical(long position) throws IOException { + public void positionPhysical(long position) throws IOException { file.seek(position); } @@ -110,7 +110,7 @@ long readPhysicalLong() throws IOException { return file.readLong(); } - void readPhysicalFully(byte[] dest, int offset, int length) throws IOException { + public void readPhysicalFully(byte[] dest, int offset, int length) throws IOException { file.readFully(dest, offset, length); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java index 75169e816a99..36eff5b41064 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,16 +28,20 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.List; +import jdk.jfr.internal.consumer.ChunkHeader; +import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.util.UserDataException; import jdk.jfr.internal.util.UserSyntaxException; @@ -111,14 +115,36 @@ private List listJFRFiles(Path path) throws UserDataException { } private void transferTo(List sourceFiles, Path output, FileChannel out) throws UserDataException { - long pos = 0; for (Path p : sourceFiles) { + long pos = 0; + long rem = 0; + try (RecordingInput input = new RecordingInput(p.toFile())) { + HeaderData hd = HeaderData.read(input); + if (hd == null) { + println("Skipping recording chunk that is being updated " + p ); + continue; + } + if (hd.finished()) { + rem = Files.size(p); + } else { + hd.markFinished(); + hd.write(out); + println("Truncating unfinished recording chunk " + p); + rem = hd.size() - ChunkHeader.HEADER_SIZE; + pos = ChunkHeader.HEADER_SIZE; + } + } catch (IOException e) { + println("Skipping recording chunk " + p + " due to: " + e.getMessage()); + continue; + } println(" " + p.toString()); try (FileChannel sourceChannel = FileChannel.open(p)) { - long rem = Files.size(p); while (rem > 0) { long n = Math.min(rem, 1024 * 1024); - long w = out.transferFrom(sourceChannel, pos, n); + long w = sourceChannel.transferTo(pos, n, out); + if (w == 0) { + throw new IOException("Could not transfer remaining bytes"); + } pos += w; rem -= w; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/HeaderData.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/HeaderData.java new file mode 100644 index 000000000000..79d090f34a41 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/HeaderData.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.tool; + +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.ByteBuffer; +import jdk.jfr.internal.consumer.ChunkHeader; +import jdk.jfr.internal.consumer.RecordingInput; + +final class HeaderData { + private static int FILE_STATE_POSITION = (int) ChunkHeader.FILE_STATE_POSITION; + private static int CHUNK_SIZE_POSITION = (int) ChunkHeader.CHUNK_SIZE_POSITION; + private static int HEADER_SIZE = (int) ChunkHeader.HEADER_SIZE; + + private final ByteBuffer buffer; + + HeaderData(byte[] bytes) { + buffer = ByteBuffer.wrap(bytes); + } + + boolean finished() { + return buffer.get(FILE_STATE_POSITION) == 0; + } + + long size() { + return buffer.getLong(CHUNK_SIZE_POSITION); + } + + void markFinished() { + buffer.put(FILE_STATE_POSITION, (byte) 0); + } + + void write(FileChannel out) throws IOException { + while (buffer.hasRemaining()) { + out.write(buffer); + } + } + + static HeaderData read(RecordingInput input) throws IOException { + byte[] first = new byte[HEADER_SIZE]; + byte[] second = new byte[HEADER_SIZE]; + while (true) { + while (true) { + input.positionPhysical(0); + input.readPhysicalFully(first, 0, first.length); + if (first[FILE_STATE_POSITION] != ChunkHeader.UPDATING_CHUNK_HEADER) { + break; + } + try { + input.pollWait(); + } catch (IOException ioe) { + return null; + } + } + input.positionPhysical(0); + input.readPhysicalFully(second, 0, second.length); + if (first[FILE_STATE_POSITION] == second[FILE_STATE_POSITION]) { + return new HeaderData(first); + } + } + } +} \ No newline at end of file diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntry.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntry.java new file mode 100644 index 000000000000..8340765dd7c8 --- /dev/null +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntry.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.internal; + +import java.util.Objects; +import jdk.jpackage.internal.util.Enquoter; + +/** + * A subset of desktop entries set by jpackage. + *

+ * See Recognized + * desktop entry keys for the full set. + */ +enum DesktopEntry { + + MIME_TYPE("MimeType"), + NAME("Name"), + COMMENT("Comment"), + EXEC("Exec"), + PATH("Path"), + ICON("Icon"), + TERMINAL("Terminal"), + TYPE("Type"), + CATEGORIES("Categories"), + ; + + DesktopEntry(String desktopEntryKey) { + this.desktopEntryKey = Objects.requireNonNull(desktopEntryKey); + } + + String formatDesktopFileEntryValue(String v) { + Objects.requireNonNull(v); + return switch (this) { + case MIME_TYPE, CATEGORIES -> ensureEndsWithSemicolon(v); + case EXEC -> Enquoter.forPropertyValues().applyTo(v); + default -> v; + }; + } + + String formatDesktopFileEntry(String v) { + return desktopEntryKey + "=" + formatDesktopFileEntryValue(v); + } + + String entryKey() { + return desktopEntryKey; + } + + private static String ensureEndsWithSemicolon(String str) { + if (!str.endsWith(";")) { + return str + ';'; + } else { + return str; + } + } + + private final String desktopEntryKey; +} diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntryFileValidator.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntryFileValidator.java new file mode 100644 index 000000000000..e5c6c082141a --- /dev/null +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopEntryFileValidator.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.internal; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.concurrent.atomic.AtomicBoolean; +import jdk.jpackage.internal.util.CommandOutputControl.Result; + + +@FunctionalInterface +interface DesktopEntryFileValidator { + + Result validate(Path desktopEntryFile); + + /** + * Creates desktop entry file validator that will run the + * {@code desktop-file-validate} command in every invocation of the + * {@link #validate(Path)} until the first failure to execute the command. In + * such an event, the validator will return a {@link Result} without the exit + * code and will keep returning such a value in subsequent invocations without + * calling the command. + * + * @return the desktop entry file validator + */ + static DesktopEntryFileValidator createDefault() { + return new DesktopEntryFileValidator() { + + @Override + public Result validate(Path desktopEntryFile) { + if (stop.get()) { + return EMPTY_RESULT; + } else { + try { + return Executor.of("desktop-file-validate".toString(), desktopEntryFile.toString()).execute(); + } catch (IOException ex) { + // The command probably isn't available. + Log.trace(ex); + // Return result without the exit code. + stop.set(true); + return EMPTY_RESULT; + } + } + } + + private final AtomicBoolean stop = new AtomicBoolean(); + + private static final Result EMPTY_RESULT = Result.build().create(); + }; + } + +} diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java index fad901699c35..f2499897ad96 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java @@ -34,12 +34,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.imageio.ImageIO; import javax.xml.stream.XMLStreamException; @@ -50,7 +54,6 @@ import jdk.jpackage.internal.model.LinuxPackage; import jdk.jpackage.internal.model.Package; import jdk.jpackage.internal.util.CompositeProxy; -import jdk.jpackage.internal.util.Enquoter; import jdk.jpackage.internal.util.PathUtils; import jdk.jpackage.internal.util.XmlUtils; @@ -138,6 +141,21 @@ static ShellCustomAction create(BuildEnv env, Package pkg) { (LinuxLauncher) pkg.app().mainLauncher().orElseThrow()); } + SortedMap cookedDesktopEntryFiles() { + return unfold().flatMap(v -> { + return v.desktopFile.stream().map(InstallableFile::srcPath).map(path -> { + return Map.entry(v.launcher, path); + }); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { + throw new IllegalStateException(); + }, () -> { + // The main launcher first; additional launchers follow, sorted by name. + return new TreeMap<>(Comparator.comparingInt(launcher -> { + return launcher == pkg.app().mainLauncher().orElseThrow() ? 0 : 1; + }).thenComparing(LinuxLauncher::name)); + })); + } + @Override List requiredPackages() { return Stream.of(List.of(this), nestedIntegrations).flatMap( @@ -220,12 +238,12 @@ private Map createDataForDesktopFile() { var installedLayout = pkg.asInstalledPackageApplicationLayout().orElseThrow(); Map data = new HashMap<>(); - data.put("APPLICATION_NAME", launcher.name()); - data.put("APPLICATION_DESCRIPTION", launcher.description()); + data.put("APPLICATION_NAME", DesktopEntry.NAME.formatDesktopFileEntryValue(launcher.name())); + data.put("APPLICATION_DESCRIPTION", DesktopEntry.COMMENT.formatDesktopFileEntryValue(launcher.description())); data.put("APPLICATION_ICON", iconFile.map( - f -> f.installPath().toString()).orElse(null)); - data.put("DEPLOY_BUNDLE_CATEGORY", pkg.menuGroupName()); - data.put("APPLICATION_LAUNCHER", Enquoter.forPropertyValues().applyTo( + f -> DesktopEntry.ICON.formatDesktopFileEntryValue(f.installPath().toString())).orElse(null)); + data.put("DEPLOY_BUNDLE_CATEGORY", DesktopEntry.CATEGORIES.formatDesktopFileEntryValue(pkg.menuGroupName())); + data.put("APPLICATION_LAUNCHER", DesktopEntry.EXEC.formatDesktopFileEntryValue( installedLayout.launchersDirectory().resolve(launcher.executableNameWithSuffix()).toString())); data.put("STARTUP_DIRECTORY", launcher.shortcut() .flatMap(LauncherShortcut::startupDirectory) @@ -241,13 +259,15 @@ private Map createDataForDesktopFile() { throw new AssertionError(); } } - }).map(str -> { - return "Path=" + str; - }).orElse(null)); + }).map(Path::toString).map(DesktopEntry.PATH::formatDesktopFileEntry).orElse(null)); return data; } + private Stream unfold() { + return Stream.concat(Stream.of(this), nestedIntegrations.stream().flatMap(DesktopIntegration::unfold)); + } + /** * Shell commands to integrate something with desktop. */ @@ -413,7 +433,17 @@ private void addFileAssociationIconFiles(ShellCommands shellCommands) private void saveDesktopFile(Map data) throws IOException { List mimeTypes = getMimeTypeNamesFromFileAssociations(); - data.put("DESKTOP_MIMES", "MimeType=" + String.join(";", mimeTypes)); + // Don't write an empty "MimeType" desktop entry. + // To pass validation with the older desktop-file-validate command, + // the value must end with a semicolon (;). + // If the list is empty, the value of the entry becomes a semicolon + // and barely passes validation with a newer desktop-file-validate command; + // it emits a non-fatal error: + // + // (error: (will be fatal in the future): value ";" for key "MimeType" in group "Desktop Entry" contains value "" which is an invalid MIME type: "" does not contain a subtype). + // + data.put("DESKTOP_MIMES", mimeTypes.isEmpty() ? null + : DesktopEntry.MIME_TYPE.formatDesktopFileEntry(String.join(";", mimeTypes))); // prepare desktop shortcut desktopFileResource diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java index baf5e0bbbf09..32edae461195 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java @@ -136,7 +136,8 @@ private static Result adjustPackageArch(LinuxSystemEnvir }); } else { return LinuxPackageArch.create(type).map(arch -> { - return new LinuxSystemEnvironment.Stub(sysEnv.soLookupAvailable(), sysEnv.nativePackageType(), arch); + return new LinuxSystemEnvironment.Stub( + sysEnv.soLookupAvailable(), sysEnv.nativePackageType(), arch, sysEnv.desktopEntryFileValidator()); }); } } diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java index 65efd9fc4c64..eb8a64139057 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java @@ -155,7 +155,7 @@ protected void buildPackage() throws IOException { // run dpkg Executor.of(cmdline).retryOnKnownErrorMessage( - "semop(1): encountered an error: Invalid argument").execute(); + "semop(1): encountered an error: Invalid argument").execute().expectExitCode(0); } @Override diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxFromOptions.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxFromOptions.java index 7fd9fd80d7e6..2097d35c3382 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxFromOptions.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxFromOptions.java @@ -36,6 +36,7 @@ import static jdk.jpackage.internal.cli.StandardOption.LINUX_RELEASE; import static jdk.jpackage.internal.cli.StandardOption.LINUX_RPM_LICENSE_TYPE; import static jdk.jpackage.internal.cli.StandardOption.LINUX_SHORTCUT_HINT; +import static jdk.jpackage.internal.cli.StandardOption.TEMP_ROOT; import static jdk.jpackage.internal.model.StandardPackageType.LINUX_DEB; import static jdk.jpackage.internal.model.StandardPackageType.LINUX_RPM; @@ -126,7 +127,11 @@ private static LinuxPackageBuilder createLinuxPackageBuilder(Options options, Li LINUX_PACKAGE_DEPENDENCIES.ifPresentIn(options, pkgBuilder::additionalDependencies); LINUX_APP_CATEGORY.ifPresentIn(options, pkgBuilder::category); - LINUX_MENU_GROUP.ifPresentIn(options, pkgBuilder::menuGroupName); + LINUX_MENU_GROUP.ifPresentIn(options, v -> { + pkgBuilder.menuGroupName(v) + .probeMenuGroupNameFile(TEMP_ROOT.getFrom(options).resolve("desktop-file-validate/probe.desktop")); + pkgBuilder.desktopEntryFileValidator(sysEnv.desktopEntryFileValidator()); + }); LINUX_RELEASE.ifPresentIn(options, pkgBuilder::release); LINUX_PACKAGE_NAME.ifPresentIn(options, pkgBuilder::literalName); diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBuilder.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBuilder.java index cd4d674432ec..60cd81824463 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBuilder.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBuilder.java @@ -26,12 +26,17 @@ import static jdk.jpackage.internal.I18N.buildConfigException; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; import jdk.jpackage.internal.model.AppImageLayout; import jdk.jpackage.internal.model.ApplicationLayout; +import jdk.jpackage.internal.model.ConfigException; import jdk.jpackage.internal.model.LinuxApplication; import jdk.jpackage.internal.model.LinuxPackage; import jdk.jpackage.internal.model.LinuxPackageMixin; @@ -71,6 +76,12 @@ LinuxPackage create() { final var app = ApplicationBuilder.overrideAppImageLayout(pkgBuilder.app(), relativeInstalledLayout); + menuGroupName().filter(_ -> { + return desktopEntryFileValidator != null && probeMenuGroupNameFile != null; + }).ifPresent(v -> { + validateMenuGroupName(desktopEntryFileValidator, probeMenuGroupNameFile, v); + }); + return create(pkgBuilder .app(LinuxApplication.create(app)) .installedPackageLayout(relativeInstalledLayout.resolveAt(Path.of("/")).resetRootDirectory()) @@ -79,7 +90,7 @@ LinuxPackage create() { private LinuxPackage create(Package pkg) { return LinuxPackage.create(pkg, new LinuxPackageMixin.Stub( - Optional.ofNullable(menuGroupName).orElseGet(DEFAULTS::menuGroupName), + menuGroupName().orElseGet(DEFAULTS::menuGroupName), category(), Optional.ofNullable(additionalDependencies), release(), @@ -96,6 +107,10 @@ LinuxPackageBuilder menuGroupName(String v) { return this; } + Optional menuGroupName() { + return Optional.ofNullable(menuGroupName); + } + LinuxPackageBuilder category(String v) { category = v; return this; @@ -124,6 +139,16 @@ LinuxPackageBuilder arch(LinuxPackageArch v) { return this; } + LinuxPackageBuilder probeMenuGroupNameFile(Path v) { + probeMenuGroupNameFile = v; + return this; + } + + LinuxPackageBuilder desktopEntryFileValidator(DesktopEntryFileValidator v) { + desktopEntryFileValidator = v; + return this; + } + private static LinuxApplicationLayout usrTreePackageLayout(Path prefix, String packageName) { final var lib = prefix.resolve(Path.of("lib", packageName)); return LinuxApplicationLayout.create( @@ -134,6 +159,7 @@ private static LinuxApplicationLayout usrTreePackageLayout(Path prefix, String p .desktopIntegrationDirectory(lib) .appModsDirectory(lib.resolve("app/mods")) .contentDirectory(lib) + .resourcesDirectory(lib) .create(), lib.resolve("lib/libapplauncher.so")); } @@ -181,6 +207,35 @@ private static void validatePackageName(String packageName, StandardPackageType } } + private static void validateMenuGroupName(DesktopEntryFileValidator desktopEntryFileValidator, Path probeFile, String menuGroupName) { + Objects.requireNonNull(desktopEntryFileValidator); + Objects.requireNonNull(probeFile); + Objects.requireNonNull(menuGroupName); + + try { + Files.createDirectories(probeFile.getParent()); + Files.write(probeFile, List.of( + "[Desktop Entry]", + DesktopEntry.NAME.formatDesktopFileEntry("acme"), + DesktopEntry.EXEC.formatDesktopFileEntry("foo"), + DesktopEntry.TYPE.formatDesktopFileEntry("Application"), + DesktopEntry.CATEGORIES.formatDesktopFileEntry(menuGroupName))); + } catch (IOException ex) { + // This is fatal if we can't create a probe file. + throw new UncheckedIOException(ex); + } + + var result = desktopEntryFileValidator.validate(probeFile); + result.exitCode().ifPresent(exitCode -> { + if (exitCode != 0) { + // Validation failed as the command returned an unexpected exit code. + throw new ConfigException( + I18N.format("error.parameter-invalid-value", menuGroupName, "--linux-menu-group"), + I18N.format("error.invalid-desktop-category.advice")); + } + }); + } + private record Defaults(String menuGroupName) { } @@ -189,6 +244,8 @@ private record Defaults(String menuGroupName) { private String category; private String additionalDependencies; private String release; + private Path probeMenuGroupNameFile; + private DesktopEntryFileValidator desktopEntryFileValidator; private LinuxPackageArch arch; private final PackageBuilder pkgBuilder; diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackager.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackager.java index 63f35fd6a659..810fd0ca82f1 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackager.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackager.java @@ -28,11 +28,14 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.SortedMap; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -40,24 +43,36 @@ import jdk.jpackage.internal.PackagingPipeline.PrimaryTaskID; import jdk.jpackage.internal.PackagingPipeline.TaskID; import jdk.jpackage.internal.model.ConfigException; +import jdk.jpackage.internal.model.JPackageException; +import jdk.jpackage.internal.model.LinuxLauncher; import jdk.jpackage.internal.model.LinuxPackage; abstract class LinuxPackager implements Consumer { LinuxPackager(BuildEnv env, T pkg, Path outputDir, LinuxSystemEnvironment sysEnv) { this.env = Objects.requireNonNull(env); + this.sysEnv = Objects.requireNonNull(sysEnv); this.pkg = Objects.requireNonNull(pkg); this.outputDir = Objects.requireNonNull(outputDir); this.withRequiredPackagesLookup = isWithRequiredPackagesSearch(sysEnv, pkg); + var desktopIntegration = DesktopIntegration.create(env, pkg); + + if (desktopIntegration instanceof DesktopIntegration di) { + cookedDesktopEntryFiles = di.cookedDesktopEntryFiles(); + } else { + cookedDesktopEntryFiles = Collections.emptySortedMap(); + } + customActions = List.of( - DesktopIntegration.create(env, pkg), + desktopIntegration, LinuxLaunchersAsServices.create(env, pkg)); } enum LinuxPackageTaskID implements TaskID { INIT_REQUIRED_PACKAGES, - VERIFY_PACKAGE + VERIFY_PACKAGE, + VALIDATE_DESKTOP_ENTRY_FILES, } @Override @@ -66,6 +81,11 @@ public void accept(PackagingPipeline.Builder pipelineBuilder) { .task(PackageTaskID.CREATE_CONFIG_FILES) .action(this::buildConfigFiles) .add() + .task(LinuxPackageTaskID.VALIDATE_DESKTOP_ENTRY_FILES) + .addDependency(PackageTaskID.CREATE_CONFIG_FILES) + .addDependent(PackageTaskID.CREATE_PACKAGE_FILE) + .action(this::validateDesktopEntryFiles) + .add() .task(LinuxPackageTaskID.INIT_REQUIRED_PACKAGES) .addDependencies(PrimaryTaskID.BUILD_APPLICATION_IMAGE, PrimaryTaskID.COPY_APP_IMAGE) .addDependent(PackageTaskID.CREATE_CONFIG_FILES) @@ -79,6 +99,10 @@ public void accept(PackagingPipeline.Builder pipelineBuilder) { .task(PackageTaskID.CREATE_PACKAGE_FILE) .action(this::buildPackage) .add(); + + if (cookedDesktopEntryFiles.isEmpty()) { + pipelineBuilder.task(LinuxPackageTaskID.VALIDATE_DESKTOP_ENTRY_FILES).noaction(); + } } protected final Path outputPackageFile() { @@ -159,6 +183,48 @@ private List findRequiredPackages() throws IOException { return lookup.execute(env.appImageDir()); } + private void validateDesktopEntryFiles() { + + List errorMessages = new ArrayList<>(); + + for (var e : cookedDesktopEntryFiles.entrySet()) { + var result = sysEnv.desktopEntryFileValidator().validate(e.getValue()); + result.exitCode().ifPresent(exitCode -> { + if (exitCode != 0) { + if (e.getKey() == pkg.app().mainLauncher().orElseThrow()) { + errorMessages.add(I18N.format( + "error.invalid-desktop-entry-file.main-launcher", e.getValue())); + } else { + errorMessages.add(I18N.format( + "error.invalid-desktop-entry-file.add-launcher", e.getValue(), e.getKey().name())); + } + } + }); + } + + if (errorMessages.isEmpty()) { + return; + } + + var advice = I18N.format("error.invalid-desktop-entry-file.advice"); + + // + // Order exceptions such that in the error output they appear + // in the same order as error messages in the `errorMessages` list. + // Add a single advice entry to the error output. + // + + throw Stream.concat( + Stream.of(errorMessages.getLast()).map(message -> { + return new ConfigException(message, advice); + }), + errorMessages.stream().limit(errorMessages.size() - 1).map(JPackageException::new) + ).reduce((a, b) -> { + a.addSuppressed(b); + return a; + }).orElseThrow(); + } + private void verifyOutputPackage() { final List errors; try { @@ -178,9 +244,11 @@ private void verifyOutputPackage() { } protected final BuildEnv env; + private final LinuxSystemEnvironment sysEnv; protected final T pkg; protected final Path outputDir; private final boolean withRequiredPackagesLookup; private List requiredPackages; - private final List customActions; + private final Collection customActions; + private final SortedMap cookedDesktopEntryFiles; } diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackagingPipeline.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackagingPipeline.java index 4b846db32316..d84c7fcae7fc 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackagingPipeline.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackagingPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,6 +113,7 @@ private static void writeLauncherIcons( .desktopIntegrationDirectory("lib") .appModsDirectory("lib/app/mods") .contentDirectory("lib") + .resourcesDirectory("lib") .create(); static final LinuxApplicationLayout APPLICATION_LAYOUT = LinuxApplicationLayout.create( diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxSystemEnvironment.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxSystemEnvironment.java index d58d3e8b40da..7813cc959cd2 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxSystemEnvironment.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxSystemEnvironment.java @@ -40,6 +40,7 @@ interface LinuxSystemEnvironment extends SystemEnvironment { boolean soLookupAvailable(); PackageType nativePackageType(); LinuxPackageArch packageArch(); + DesktopEntryFileValidator desktopEntryFileValidator(); static Result create() { return detectNativePackageType().map(LinuxSystemEnvironment::create).orElseGet(() -> { @@ -64,7 +65,11 @@ static Optional detectNativePackageType() { static Result create(StandardPackageType nativePackageType) { return LinuxPackageArch.create(nativePackageType).map(arch -> { - return new Stub(LibProvidersLookup.supported(), nativePackageType, arch); + return new Stub( + LibProvidersLookup.supported(), + nativePackageType, + arch, + DesktopEntryFileValidator.createDefault()); }); } @@ -87,7 +92,11 @@ static Result mixin(Class type, } } - record Stub(boolean soLookupAvailable, PackageType nativePackageType, LinuxPackageArch packageArch) implements LinuxSystemEnvironment { + record Stub( + boolean soLookupAvailable, + PackageType nativePackageType, + LinuxPackageArch packageArch, + DesktopEntryFileValidator desktopEntryFileValidator) implements LinuxSystemEnvironment { } static final class Internal { diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties index dcdc96323ef3..be6b61147798 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties @@ -48,6 +48,11 @@ error.deb-invalid-value-for-package-name.advice=Set the "--linux-package-name" o error.rpm-invalid-value-for-package-name=Invalid value "{0}" for the package name. error.rpm-invalid-value-for-package-name.advice=Set the "--linux-package-name" option to a valid RPM package name. Note that the package names must consist only of letters (a-z, A-Z), digits (0-9), plus (+) and minus (-) signs, periods (.) and underscores (_). They must be at least one character long and must start with a letter. +error.invalid-desktop-category.advice=Specify a value that is valid for the "Categories" key in a desktop entry file and passes validation by the desktop-file-validate command +error.invalid-desktop-entry-file.main-launcher=Invalid main desktop entry file "{0}" +error.invalid-desktop-entry-file.add-launcher=Invalid desktop entry file "{0}" for the [{1}] additional launcher +error.invalid-desktop-entry-file.advice=Use a desktop entry file template that passes validation by the desktop-file-validate command + error.rpm-arch-not-detected="Failed to detect RPM arch" message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java index 25d97e155079..d0724648e36b 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java @@ -667,6 +667,7 @@ public void execute(TaskAction taskAction) throws IOException { .desktopIntegrationDirectory("Contents/Resources") .appModsDirectory("Contents/app/mods") .contentDirectory("Contents") + .resourcesDirectory("Contents/Resources") .create(); static final MacApplicationLayout APPLICATION_LAYOUT = MacApplicationLayout.create( diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java index bb5f1a98a995..cd0ff8d0da2a 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java @@ -65,6 +65,7 @@ final class ApplicationBuilder { appDirSources = other.appDirSources; externalApp = other.externalApp; contentDirSources = other.contentDirSources; + resourcesDirSources = other.resourcesDirSources; appImageLayout = other.appImageLayout; runtimeBuilder = other.runtimeBuilder; launchers = other.launchers; @@ -96,6 +97,7 @@ Application create() { Optional.ofNullable(copyright).orElseGet(DEFAULTS::copyright), Optional.ofNullable(appDirSources).orElseGet(List::of), Optional.ofNullable(contentDirSources).orElseGet(List::of), + Optional.ofNullable(resourcesDirSources).orElseGet(List::of), appImageLayout, Optional.ofNullable(runtimeBuilder), launchersAsList, @@ -179,6 +181,11 @@ ApplicationBuilder contentDirSources(Collection v) { return this; } + ApplicationBuilder resourcesDirSources(Collection v) { + resourcesDirSources = v; + return this; + } + ApplicationBuilder derivedVersionNormalizer(UnaryOperator v) { derivedVersionNormalizer = v; return this; @@ -339,6 +346,7 @@ static Application overrideAppImageLayout(Application app, AppImageLayout appIma app.copyright(), app.appDirSources(), app.contentDirSources(), + app.resourcesDirSources(), Objects.requireNonNull(appImageLayout), app.runtimeBuilder(), app.launchers(), @@ -388,6 +396,7 @@ String copyright() { private Collection appDirSources; private ExternalApplication externalApp; private Collection contentDirSources; + private Collection resourcesDirSources; private AppImageLayout appImageLayout; private RuntimeBuilder runtimeBuilder; private ApplicationLaunchers launchers; diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java index 5edc4d69c813..8a42004da3a5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java @@ -85,6 +85,7 @@ static ApplicationImageTaskAction createCopyCont return env -> { for (var e : List.of( Map.entry(env.app().appDirSources(), env.resolvedLayout().appDirectory()), + Map.entry(env.app().resourcesDirSources(), env.resolvedLayout().resourcesDirectory()), Map.entry(env.app().contentDirSources(), env.resolvedLayout().contentDirectory()) )) { RootedPath.copy(e.getKey().stream(), e.getValue(), diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BuildEnvBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BuildEnvBuilder.java index 77354cb2c53f..aa0e0f357eb2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BuildEnvBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BuildEnvBuilder.java @@ -24,8 +24,6 @@ */ package jdk.jpackage.internal; -import static jdk.jpackage.internal.cli.StandardValidator.IS_DIRECTORY_EMPTY_OR_NON_EXISTENT_PREDICATE; - import java.nio.file.Path; import java.util.Objects; import java.util.Optional; @@ -41,13 +39,6 @@ final class BuildEnvBuilder { } BuildEnv create() { - // The directory should be validated earlier with a proper error message. - // Here is only a sanity check. - if (!IS_DIRECTORY_EMPTY_OR_NON_EXISTENT_PREDICATE.test(root)) { - throw new UnsupportedOperationException( - String.format("Root work directory [%s] should be empty or non existent", root)); - } - return BuildEnv.create( root, Optional.ofNullable(resourceDir), diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java index 4b4e6f9dbac3..f2b2290d9c15 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java @@ -31,6 +31,7 @@ import static jdk.jpackage.internal.cli.StandardOption.ADDITIONAL_LAUNCHERS; import static jdk.jpackage.internal.cli.StandardOption.ADD_MODULES; import static jdk.jpackage.internal.cli.StandardOption.APP_CONTENT; +import static jdk.jpackage.internal.cli.StandardOption.APP_RESOURCES; import static jdk.jpackage.internal.cli.StandardOption.APP_VERSION; import static jdk.jpackage.internal.cli.StandardOption.COPYRIGHT; import static jdk.jpackage.internal.cli.StandardOption.DESCRIPTION; @@ -187,6 +188,10 @@ private static ApplicationBuilder createApplicationBuilder( // from the original list of source files for the given destination file. return v.reversed().stream().flatMap(Collection::stream).toList(); }).ifPresent(appBuilder::contentDirSources); + APP_RESOURCES.findIn(options).map((List> v) -> { + return v.reversed().stream().flatMap(Collection::stream).toList(); + }).ifPresent(appBuilder::resourcesDirSources); + if (isRuntimeInstaller) { appBuilder.appImageLayout(runtimeLayout); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardHelpFormatter.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardHelpFormatter.java index d938e6022570..0845b9e765e5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardHelpFormatter.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardHelpFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,7 +207,8 @@ private static Stream> genericOptions() { private static Stream> appImageOptions() { return Stream.of( StandardOption.INPUT, - StandardOption.APP_CONTENT + StandardOption.APP_CONTENT, + StandardOption.APP_RESOURCES ).map(OptionValue::getSpec); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java index 1cfdf3261105..2fde8ebb3f24 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java @@ -222,6 +222,17 @@ public boolean test(Path path) { })) .createArray(toExplodedPathList()); + public static final OptionValue>> APP_RESOURCES = existingPathOption("app-resources") + .tokenizer(pathSeparator()) + .valuePattern("additional resources") + .description("help.option.app-resources" + resourceKeySuffix(OperatingSystem.current())) + .outOfScope(NOT_BUILDING_APP_IMAGE) + .map(explodedPathOptionMapper(explodedPathConverter().withPathFileName().create())) + .mutate(createOptionSpecBuilderMutator((b, context) -> { + b.description("help.option.app-resources" + resourceKeySuffix(context.os())); + })) + .createArray(toExplodedPathList()); + static final OptionValue FILE_ASSOCIATIONS_INTERNAL = fileOption("file-associations") .tokenizer(pathSeparator()) .outOfScope(BundlingOperationModifier.BUNDLE_RUNTIME) diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/Application.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/Application.java index 7860a04faacd..3a594e9f6ae4 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/Application.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/Application.java @@ -100,6 +100,15 @@ public non-sealed interface Application extends BundleSpec { */ Collection contentDirSources(); + /** + * Gets the source paths that should be copied into + * {@link ApplicationLayout#resourcesDirectory()} directory of the image of this + * application. + * + * @return the source paths + */ + Collection resourcesDirSources(); + /** * Gets the unresolved app image layout of this application. * @@ -252,6 +261,7 @@ record Stub( String copyright, Collection appDirSources, Collection contentDirSources, + Collection resourcesDirSources, AppImageLayout imageLayout, Optional runtimeBuilder, List launchers, diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayout.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayout.java index 013d2fc78cdd..e0935cec9304 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayout.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,6 +100,7 @@ private Builder(ApplicationLayout appLayout) { appModsDirectory = appLayout.appModsDirectory(); desktopIntegrationDirectory = appLayout.desktopIntegrationDirectory(); contentDirectory = appLayout.contentDirectory(); + resourcesDirectory = appLayout.resourcesDirectory(); } public ApplicationLayout create() { @@ -111,11 +112,13 @@ public ApplicationLayout create() { Objects.requireNonNull(appModsDirectory); Objects.requireNonNull(desktopIntegrationDirectory); Objects.requireNonNull(contentDirectory); + Objects.requireNonNull(resourcesDirectory); return ApplicationLayout.create(new AppImageLayout.Stub( rootDirectory, runtimeDirectory), new ApplicationLayoutMixin.Stub( launchersDirectory, appDirectory, appModsDirectory, - desktopIntegrationDirectory, contentDirectory)); + desktopIntegrationDirectory, contentDirectory, + resourcesDirectory)); } public Builder setAll(String path) { @@ -130,6 +133,7 @@ public Builder setAll(Path path) { appModsDirectory(path); desktopIntegrationDirectory(path); contentDirectory(path); + resourcesDirectory(path); return this; } @@ -141,6 +145,7 @@ public Builder mutate(UnaryOperator mapper) { appModsDirectory(mapNullablePath(mapper, appModsDirectory)); desktopIntegrationDirectory(mapNullablePath(mapper, desktopIntegrationDirectory)); contentDirectory(mapNullablePath(mapper, contentDirectory)); + resourcesDirectory(mapNullablePath(mapper, resourcesDirectory)); return this; } @@ -207,6 +212,15 @@ public Builder contentDirectory(Path v) { return this; } + public Builder resourcesDirectory(String v) { + return resourcesDirectory(Path.of(v)); + } + + public Builder resourcesDirectory(Path v) { + resourcesDirectory = v; + return this; + } + private Path rootDirectory = Path.of(""); private Path launchersDirectory; private Path appDirectory; @@ -214,5 +228,6 @@ public Builder contentDirectory(Path v) { private Path appModsDirectory; private Path desktopIntegrationDirectory; private Path contentDirectory; + private Path resourcesDirectory; } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayoutMixin.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayoutMixin.java index 10528b7bd6af..9be8b5688c30 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayoutMixin.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayoutMixin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,9 +56,14 @@ public interface ApplicationLayoutMixin { */ Path contentDirectory(); + /** + * Path to directory with additional application resources. + */ + Path resourcesDirectory(); + /** * Default implementation of {@link ApplicationLayoutMixin} interface. */ - record Stub(Path launchersDirectory, Path appDirectory, Path appModsDirectory, Path desktopIntegrationDirectory, Path contentDirectory) implements ApplicationLayoutMixin { + record Stub(Path launchersDirectory, Path appDirectory, Path appModsDirectory, Path desktopIntegrationDirectory, Path contentDirectory, Path resourcesDirectory) implements ApplicationLayoutMixin { } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties index 90f4a579bfec..4b058097f23e 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties @@ -134,11 +134,15 @@ help.option.add-modules=\ help.option.app-content=\ \ A comma separated list of paths to files and/or directories\n\ \ to add to the application payload.\n\ +\ --app-content is processed after --app-resources, independent\n\ +\ of command-line order.\n\ \ This option can be used more than once. help.option.app-content.mac=\ \ A comma separated list of paths to files and/or directories\n\ \ to add to the application payload.\n\ +\ --app-content is processed after --app-resources, independent\n\ +\ of command-line order.\n\ \ This option can be used more than once.\n\ \ Note: The value should be a directory with the "Resources"\n\ \ subdirectory (or any other directory that is valid in the "Contents"\n\ @@ -146,6 +150,27 @@ help.option.app-content.mac=\ \ invalid application bundle which may fail code signing and/or\n\ \ notarization. +help.option.app-resources.linux=\ +\ A colon-separated list of paths to files and/or directories\n\ +\ to add to the application's "lib" directory.\n\ +\ If a file from --app-resources conflicts with one from\n\ +\ --app-content, the file from --app-content is used.\n\ +\ This option can be used more than once. + +help.option.app-resources.mac=\ +\ A colon-separated list of paths to files and/or directories\n\ +\ to add to the application's "Contents/Resources" directory.\n\ +\ If a file from --app-resources conflicts with one from\n\ +\ --app-content, the file from --app-content is used.\n\ +\ This option can be used more than once. + +help.option.app-resources.win=\ +\ A semicolon-separated list of paths to files and/or directories\n\ +\ to add to the application image root directory.\n\ +\ If a file from --app-resources conflicts with one from\n\ +\ --app-content, the file from --app-content is used.\n\ +\ This option can be used more than once. + help.option.app-image=\ \ Location of the predefined application image that is used\n\ \ to build an installable package\n\ diff --git a/src/jdk.jpackage/share/man/jpackage.md b/src/jdk.jpackage/share/man/jpackage.md index 3467c53e5955..8b34a56b4f04 100644 --- a/src/jdk.jpackage/share/man/jpackage.md +++ b/src/jdk.jpackage/share/man/jpackage.md @@ -255,6 +255,9 @@ The `jpackage` tool will take as input a Java application and a Java run-time im : A comma separated list of paths to files and/or directories to add to the application payload. + --app-content is processed after --app-resources, independent + of command-line order. + This option can be used more than once. macOS note: The value should be a directory with the "Resources" @@ -263,6 +266,25 @@ The `jpackage` tool will take as input a Java application and a Java run-time im jpackage may produce invalid application bundle which may fail code signing and/or notarization. +`--app-resources` *additional-resources* + +: A list of paths to files and/or directories separated by the + platform-specific path separator (`:` on Linux and macOS; `;` on Windows), + to add to the application resources directory. + + A colliding file from --app-content replaces + one from --app-resources. + + This option can be used more than once. + + Destination: + + - Windows: application image root + + - Linux: application image lib directory + + - macOS: Contents/Resources + ### Options for creating the application launcher(s): diff --git a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp index db240aeee904..17de01505547 100644 --- a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp +++ b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp @@ -568,7 +568,7 @@ struct GtestFriendToMacroAssembler { real_mode); masm.ret(lr); - masm.flush(); // icache invalidate + masm.invalidate_icache(); } { @@ -622,15 +622,20 @@ struct GtestFriendToMacroAssembler { build_and_run_encode_decode_klass((address)(right_n_bits(highest_xor_base_bit - lowest_xor_base_bit) << lowest_xor_base_bit), shift, MA::KlassDecodeXor); - // test movk-based - // Only bits in the third quadrant and not a valid immediate - build_and_run_encode_decode_klass((address)0x0000'A000'0000'0000ULL, 0, MA::KlassDecodeMovk); - // test Fallback mode. - // base has low bits that intersect with nKlass, no other mode would work - build_and_run_encode_decode_klass((address)(0x5'0000'0000ULL + os::vm_page_size()), + // We take fallback mode if base has low bits that intersect with nKlass, and/or if it is not a + // valid logical immediate + + // Not a logical immediate + build_and_run_encode_decode_klass((address)0x0000'A000'0000'0000ULL, + shift, MA::KlassDecodeFallback); + build_and_run_encode_decode_klass((address)0x0000'0005'0000'0000ULL, + shift, MA::KlassDecodeFallback); + + // Base spills into lower bits + build_and_run_encode_decode_klass((address)(0x2'0000'0000ULL + os::vm_page_size()), shift, MA::KlassDecodeFallback); - build_and_run_encode_decode_klass((address)(0x5'0000'0000ULL - os::vm_page_size()), + build_and_run_encode_decode_klass((address)(0x2'0000'0000ULL - os::vm_page_size()), shift, MA::KlassDecodeFallback); // a base that has ones in all four quadrants to trigger the full movz+3*movk path diff --git a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp index c2de96bea4fd..f3fb298ad346 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp @@ -46,6 +46,19 @@ class G1CardSetTest : public ::testing::Test { } }; + // Verify Full card containers contents (and amount). Assumes that cards returned are in ascending order. + class G1VerifyFullCardContainerClosure : public G1CardSet::CardClosure { + public: + size_t _cur_card; + + G1VerifyFullCardContainerClosure() : _cur_card(0) { } + + void do_card(uint region_idx, uint card_idx) override { + ASSERT_TRUE(card_idx == _cur_card); + _cur_card++; + } + }; + static WorkerThreads* _workers; static uint _max_workers; @@ -374,9 +387,9 @@ void G1CardSetTest::cardset_basic_test() { res = card_set.add_card(99, CardsPerRegion - 2); ASSERT_TRUE(res == Found); - G1CountCardsClosure count_cards; + G1VerifyFullCardContainerClosure count_cards; card_set.iterate_cards(count_cards); - ASSERT_TRUE(count_cards._num_cards == config.max_cards_in_region()); + ASSERT_TRUE(count_cards._cur_card == config.max_cards_in_region()); card_set.clear(); ASSERT_TRUE(card_set.occupied() == 0); diff --git a/test/hotspot/gtest/gc/g1/test_g1CodeRootSet.cpp b/test/hotspot/gtest/gc/g1/test_g1CodeRootSet.cpp index 80f3f33bf052..389a8ae49352 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CodeRootSet.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CodeRootSet.cpp @@ -27,7 +27,7 @@ TEST_VM(G1CodeRootSet, g1_code_cache_rem_set) { G1CodeRootSet root_set; - ASSERT_TRUE(root_set.is_empty()) << "Code root set must be initially empty " + ASSERT_TRUE(root_set.length() == 0) << "Code root set must be initially empty " "but is not."; root_set.add((nmethod*) 1); @@ -51,18 +51,7 @@ TEST_VM(G1CodeRootSet, g1_code_cache_rem_set) { << "After adding in total " << num_to_add << " distinct code roots, " "they need to be in the set, but there are only " << root_set.length(); - size_t num_popped = 0; - for (size_t i = 1; i <= num_to_add; i++) { - bool removed = root_set.remove((nmethod*) i); - if (removed) { - num_popped += 1; - } else { - break; - } - } - ASSERT_EQ(num_popped, num_to_add) - << "Managed to pop " << num_popped << " code roots, but only " - << num_to_add << " were added"; + root_set.clear(); ASSERT_EQ(root_set.length(), 0u) << "should be empty"; } diff --git a/test/hotspot/gtest/gc/g1/test_g1FromCardCache.cpp b/test/hotspot/gtest/gc/g1/test_g1FromCardCache.cpp new file mode 100644 index 000000000000..f560bacd6f6e --- /dev/null +++ b/test/hotspot/gtest/gc/g1/test_g1FromCardCache.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "gc/g1/g1FromCardCache.inline.hpp" +#include "unittest.hpp" + +TEST(G1FromCardCache, hit_and_miss) { + const uintptr_t from_card = 64; + const uint cset_group_a = 3; + const uint cset_group_b = 13; + const uint cset_group_high = 1024; + + G1FromCardCache cache; + + EXPECT_FALSE(cache.contains_or_add(from_card, cset_group_a)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_a)); + + // Retain multiple cset groups for the same from_card. + EXPECT_FALSE(cache.contains_or_add(from_card, cset_group_b)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_a)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_b)); + + // A group id is not an array index. + EXPECT_FALSE(cache.contains_or_add(from_card, cset_group_high)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_high)); +} + +TEST(G1FromCardCache, from_card_transition) { + const uintptr_t from_card_a = 2; + const uintptr_t from_card_b = 3; + const uint cset_group_id = 17; + + G1FromCardCache cache; + + EXPECT_FALSE(cache.contains_or_add(from_card_a, cset_group_id)); + EXPECT_TRUE(cache.contains_or_add(from_card_a, cset_group_id)); + + // Discard previous from_card data. + EXPECT_FALSE(cache.contains_or_add(from_card_b, cset_group_id)); + EXPECT_TRUE(cache.contains_or_add(from_card_b, cset_group_id)); + + // Verify that it was discarded before. + EXPECT_FALSE(cache.contains_or_add(from_card_a, cset_group_id)); +} + +TEST(G1FromCardCache, cache_reset) { + const uintptr_t from_card = 17; + const uint cset_group_id = 17; + + G1FromCardCache cache; + + EXPECT_FALSE(cache.contains_or_add(from_card, cset_group_id)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_id)); + + cache.reset(); + + EXPECT_FALSE(cache.contains_or_add(from_card, cset_group_id)); + EXPECT_TRUE(cache.contains_or_add(from_card, cset_group_id)); +} diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp index 0b89c59634ac..9189e5af456e 100644 --- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp @@ -22,7 +22,7 @@ * */ -#include "gc/shenandoah/shenandoahAgeCensus.hpp" +#include "gc/shenandoah/shenandoahAgeCensus.inline.hpp" #include "unittest.hpp" class ShenandoahAgeCensusTest : public ::testing::Test { diff --git a/test/hotspot/gtest/logging/test_log.cpp b/test/hotspot/gtest/logging/test_log.cpp index 871f2aa9bbef..2580bf8b78a8 100644 --- a/test/hotspot/gtest/logging/test_log.cpp +++ b/test/hotspot/gtest/logging/test_log.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,7 @@ TEST_VM_F(LogTest, large_message) { fclose(fp); size_t count = 0; + ASSERT_NE(nullptr, output); for (size_t ps = 0 ; output[ps + count] != '\0'; output[ps + count] == Xchar ? count++ : ps++); EXPECT_EQ(sizeof(big_msg) - 1, count); } diff --git a/test/hotspot/gtest/oops/test_markWord.cpp b/test/hotspot/gtest/oops/test_markWord.cpp index 35a8c7bb66f7..1147d8e3ecd3 100644 --- a/test/hotspot/gtest/oops/test_markWord.cpp +++ b/test/hotspot/gtest/oops/test_markWord.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ class LockerThread : public JavaTestThread { // state we have... ObjectLocker ol(h_obj, THREAD); ol.notify_all(THREAD); - assert_test_pattern(h_obj, "monitor"); + assert_test_pattern(h_obj, "has_monitor"); } }; @@ -91,13 +91,13 @@ TEST_VM(markWord, printing) { // Thread tries to lock it. { ObjectLocker ol(h_obj, THREAD); - assert_mark_word_print_pattern(h_obj, "locked"); + assert_mark_word_print_pattern(h_obj, "is_fast_locked"); } - assert_mark_word_print_pattern(h_obj, "is_unlocked no_hash"); + assert_mark_word_print_pattern(h_obj, "is_lock_neutral no_hash"); // Hash the object then print it. intx hash = h_obj->identity_hash(); - assert_mark_word_print_pattern(h_obj, "is_unlocked hash=0x"); + assert_mark_word_print_pattern(h_obj, "is_lock_neutral hash=0x"); // Wait gets the lock inflated. { @@ -109,25 +109,24 @@ TEST_VM(markWord, printing) { st->doit(); ol.wait_uninterruptibly(THREAD); - assert_test_pattern(h_obj, "monitor"); + assert_test_pattern(h_obj, "has_monitor"); done.wait_with_safepoint_check(THREAD); // wait till the thread is done. } } -static void assert_unlocked_state(markWord mark) { - EXPECT_FALSE(mark.has_displaced_mark_helper()); +static void assert_lock_neutral_state(markWord mark) { EXPECT_FALSE(mark.is_fast_locked()); EXPECT_FALSE(mark.has_monitor()); - EXPECT_FALSE(mark.is_locked()); - EXPECT_TRUE(mark.is_unlocked()); + EXPECT_FALSE(mark.is_marked()); + EXPECT_TRUE(mark.is_lock_neutral()); } static void assert_copy_set_hash(markWord mark) { const intptr_t hash = 4711; - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); markWord copy = mark.copy_set_hash(hash); EXPECT_EQ(hash, copy.hash()); - EXPECT_FALSE(copy.has_no_hash()); + EXPECT_TRUE(copy.has_hash()); } static void assert_type(markWord mark) { @@ -137,12 +136,11 @@ static void assert_type(markWord mark) { TEST_VM(markWord, prototype) { markWord mark = markWord::prototype(); - assert_unlocked_state(mark); - EXPECT_TRUE(mark.is_neutral()); + assert_lock_neutral_state(mark); assert_type(mark); - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); EXPECT_FALSE(mark.is_marked()); assert_copy_set_hash(mark); @@ -157,13 +155,12 @@ static void assert_inline_type(markWord mark) { TEST_VM(markWord, inline_type_prototype) { markWord mark = markWord::inline_type_prototype(); - assert_unlocked_state(mark); - // Don't call mark.is_neutral() on value class instances + assert_lock_neutral_state(mark); assert_test_pattern(&mark, " inline_type"); assert_inline_type(mark); - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); EXPECT_FALSE(mark.is_marked()); } @@ -176,13 +173,12 @@ static void assert_flat_array_type(markWord mark) { TEST_VM(markWord, null_free_flat_array_prototype) { markWord mark = markWord::flat_array_prototype(true /* null_free */); - assert_unlocked_state(mark); - EXPECT_TRUE(mark.is_neutral()); + assert_lock_neutral_state(mark); assert_flat_array_type(mark); EXPECT_TRUE(mark.is_null_free_array()); - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); EXPECT_FALSE(mark.is_marked()); assert_copy_set_hash(mark); @@ -194,13 +190,12 @@ TEST_VM(markWord, null_free_flat_array_prototype) { TEST_VM(markWord, nullable_flat_array_prototype) { markWord mark = markWord::flat_array_prototype(false /* null_free */); - assert_unlocked_state(mark); - EXPECT_TRUE(mark.is_neutral()); + assert_lock_neutral_state(mark); assert_flat_array_type(mark); EXPECT_FALSE(mark.is_null_free_array()); - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); EXPECT_FALSE(mark.is_marked()); assert_copy_set_hash(mark); @@ -218,12 +213,11 @@ static void assert_null_free_array_type(markWord mark) { TEST_VM(markWord, null_free_array_prototype) { markWord mark = markWord::null_free_array_prototype(); - assert_unlocked_state(mark); - EXPECT_TRUE(mark.is_neutral()); + assert_lock_neutral_state(mark); assert_null_free_array_type(mark); - EXPECT_TRUE(mark.has_no_hash()); + EXPECT_FALSE(mark.has_hash()); EXPECT_FALSE(mark.is_marked()); assert_copy_set_hash(mark); diff --git a/test/hotspot/gtest/oops/test_objArrayOop.cpp b/test/hotspot/gtest/oops/test_objArrayOop.cpp index 1dd8cf752548..cc5bb2326882 100644 --- a/test/hotspot/gtest/oops/test_objArrayOop.cpp +++ b/test/hotspot/gtest/oops/test_objArrayOop.cpp @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/test/hotspot/gtest/opto/test_typejavaptr.cpp b/test/hotspot/gtest/opto/test_typejavaptr.cpp index 89fbebcf1e41..6bf42c251fd3 100644 --- a/test/hotspot/gtest/opto/test_typejavaptr.cpp +++ b/test/hotspot/gtest/opto/test_typejavaptr.cpp @@ -51,6 +51,17 @@ class TypeAryKlassPtrMirror; // tests. // - Mirror instances are created at compile time, ensuring the absence of unexpected behaviors. +// For GCC, UBSAN breaks the constexpr evaluation, which results in compilation failure. +// For MSVC, the constexpr evaluation mechanism on GHA seems to have a smaller computing step +// limit, which results in it failing to compute _2d_samples, which is a constexpr variable. +// Our workaround to those compiler issues is to compute the variables at runtime instead. The +// downside is that we do not benefit from the lack-of-UB guarantee of constexpr evaluation. +#ifdef __clang__ +#define MAYBE_CONSTEXPR constexpr +#else // __clang__ +#define MAYBE_CONSTEXPR const +#endif // __clang__ + class InterfaceSet { public: bool _i0; @@ -987,7 +998,7 @@ constexpr auto TypeAryPtrMirror::generate_1d_elem_samples() { return res; } -constexpr std::array, TypeAryPtrMirror::_1d_elem_samples_size> TypeAryPtrMirror::_1d_elem_samples = generate_1d_elem_samples(); +MAYBE_CONSTEXPR std::array, TypeAryPtrMirror::_1d_elem_samples_size> TypeAryPtrMirror::_1d_elem_samples = generate_1d_elem_samples(); template constexpr void TypeAryPtrMirror::fill_samples_helper(R& res, size_t& sample_idx, TypePtr::PTR ptr, InstanceMirror const_oop, const AryElemType* elem, @@ -1128,7 +1139,7 @@ constexpr auto TypeAryPtrMirror::generate_1d_samples() { return res; } -constexpr std::array TypeAryPtrMirror::_1d_samples = generate_1d_samples(); +MAYBE_CONSTEXPR std::array TypeAryPtrMirror::_1d_samples = generate_1d_samples(); constexpr auto TypeAryPtrMirror::generate_2d_elem_samples() { std::array, _2d_elem_samples_size> res; @@ -1152,7 +1163,7 @@ constexpr auto TypeAryPtrMirror::generate_2d_elem_samples() { return res; } -constexpr std::array, TypeAryPtrMirror::_2d_elem_samples_size> TypeAryPtrMirror::_2d_elem_samples = generate_2d_elem_samples(); +MAYBE_CONSTEXPR std::array, TypeAryPtrMirror::_2d_elem_samples_size> TypeAryPtrMirror::_2d_elem_samples = generate_2d_elem_samples(); constexpr auto TypeAryPtrMirror::generate_2d_samples() { std::array res; @@ -1194,7 +1205,7 @@ constexpr auto TypeAryPtrMirror::generate_2d_samples() { return res; } -constexpr std::array TypeAryPtrMirror::_2d_samples = generate_2d_samples(); +MAYBE_CONSTEXPR std::array TypeAryPtrMirror::_2d_samples = generate_2d_samples(); class TypeKlassPtrMirror : public TypePtrMirror { private: @@ -1580,7 +1591,7 @@ constexpr auto TypeAryKlassPtrMirror::generate_1d_elem_samples() { return res; } -constexpr std::array, TypeAryKlassPtrMirror::_1d_elem_samples_size> TypeAryKlassPtrMirror::_1d_elem_samples = generate_1d_elem_samples(); +MAYBE_CONSTEXPR std::array, TypeAryKlassPtrMirror::_1d_elem_samples_size> TypeAryKlassPtrMirror::_1d_elem_samples = generate_1d_elem_samples(); constexpr auto TypeAryKlassPtrMirror::generate_1d_samples() { std::array res; @@ -1628,7 +1639,7 @@ constexpr auto TypeAryKlassPtrMirror::generate_1d_samples() { return res; } -constexpr std::array TypeAryKlassPtrMirror::_1d_samples = generate_1d_samples(); +MAYBE_CONSTEXPR std::array TypeAryKlassPtrMirror::_1d_samples = generate_1d_samples(); constexpr auto TypeAryKlassPtrMirror::generate_2d_elem_samples() { std::array, _2d_elem_samples_size> res; @@ -1646,7 +1657,7 @@ constexpr auto TypeAryKlassPtrMirror::generate_2d_elem_samples() { return res; } -constexpr std::array, TypeAryKlassPtrMirror::_2d_elem_samples_size> TypeAryKlassPtrMirror::_2d_elem_samples = generate_2d_elem_samples(); +MAYBE_CONSTEXPR std::array, TypeAryKlassPtrMirror::_2d_elem_samples_size> TypeAryKlassPtrMirror::_2d_elem_samples = generate_2d_elem_samples(); constexpr auto TypeAryKlassPtrMirror::generate_2d_samples() { std::array res; @@ -1679,7 +1690,7 @@ constexpr auto TypeAryKlassPtrMirror::generate_2d_samples() { return res; } -constexpr std::array TypeAryKlassPtrMirror::_2d_samples = generate_2d_samples(); +MAYBE_CONSTEXPR std::array TypeAryKlassPtrMirror::_2d_samples = generate_2d_samples(); // OopPtrMirror is the mirror of oop class OopPtrMirror { diff --git a/test/hotspot/gtest/riscv/test_assembler_riscv.cpp b/test/hotspot/gtest/riscv/test_assembler_riscv.cpp index 55504c34b0fa..6281144fed63 100644 --- a/test/hotspot/gtest/riscv/test_assembler_riscv.cpp +++ b/test/hotspot/gtest/riscv/test_assembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,7 +48,7 @@ class CmovTester { _masm.mv(c_rarg0, c_rarg2); _masm.ret(); } - _masm.flush(); // icache invalidate + _masm.invalidate_icache(); int64_t ret = ((zicond_func)entry)(a0, a1, a2, a3); ASSERT_EQ(ret, result); BufferBlob::free(bb); @@ -175,7 +175,7 @@ class CmpxchgTester { _masm.ret(); _func = ((cmpxchg_func)entry); } - _masm.flush(); // icache invalidate + _masm.invalidate_icache(); } ~CmpxchgTester() { @@ -594,7 +594,7 @@ class WeakCmpxchgTester { _masm.ret(); _weak = ((weak_cmpxchg_func)entry); } - _masm.flush(); // icache invalidate + _masm.invalidate_icache(); } TESTSIZE weak_cmpxchg(intptr_t addr, TESTSIZE expected, TESTSIZE new_value) { diff --git a/test/hotspot/gtest/runtime/test_atomicAccess.cpp b/test/hotspot/gtest/runtime/test_atomicAccess.cpp index a489be71b192..908bd603e834 100644 --- a/test/hotspot/gtest/runtime/test_atomicAccess.cpp +++ b/test/hotspot/gtest/runtime/test_atomicAccess.cpp @@ -351,3 +351,182 @@ TEST_VM(AtomicAccessBitopsTest, int64) { TEST_VM(AtomicAccessBitopsTest, uint64) { AtomicAccessBitopsTestSupport()(); } + +// The following tests verify that atomic operations produce correct results for +// each atomic_memory_order value. They don't verify the actual ordering +// semantics (which would require multi-threaded stress tests). + +static const atomic_memory_order memory_orders[] = { + memory_order_relaxed, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, + memory_order_conservative, +}; + +template +struct AtomicAccessOrderedAddTestSupport { + volatile T _test_value; + + AtomicAccessOrderedAddTestSupport() : _test_value{} {} + + void test_add(atomic_memory_order order) { + T zero = 0; + T five = 5; + AtomicAccess::store(&_test_value, zero); + T value = AtomicAccess::add(&_test_value, five, order); + EXPECT_EQ(five, value); + EXPECT_EQ(five, AtomicAccess::load(&_test_value)); + } + + void test_fetch_add(atomic_memory_order order) { + T zero = 0; + T five = 5; + AtomicAccess::store(&_test_value, zero); + T value = AtomicAccess::fetch_then_add(&_test_value, five, order); + EXPECT_EQ(zero, value); + EXPECT_EQ(five, AtomicAccess::load(&_test_value)); + } +}; + +TEST_VM(AtomicAccessOrderedAddTest, int32) { + using Support = AtomicAccessOrderedAddTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test_add(order); + Support().test_fetch_add(order); + } +} + +TEST_VM(AtomicAccessOrderedAddTest, int64) { + using Support = AtomicAccessOrderedAddTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test_add(order); + Support().test_fetch_add(order); + } +} + +template +struct AtomicAccessOrderedXchgTestSupport { + volatile T _test_value; + + AtomicAccessOrderedXchgTestSupport() : _test_value{} {} + + void test(atomic_memory_order order) { + T zero = 0; + T five = 5; + AtomicAccess::store(&_test_value, zero); + T res = AtomicAccess::xchg(&_test_value, five, order); + EXPECT_EQ(zero, res); + EXPECT_EQ(five, AtomicAccess::load(&_test_value)); + } +}; + +TEST_VM(AtomicAccessOrderedXchgTest, int32) { + using Support = AtomicAccessOrderedXchgTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test(order); + } +} + +TEST_VM(AtomicAccessOrderedXchgTest, int64) { + using Support = AtomicAccessOrderedXchgTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test(order); + } +} + +template +struct AtomicAccessOrderedCmpxchgTestSupport { + volatile T _test_value; + + AtomicAccessOrderedCmpxchgTestSupport() : _test_value{} {} + + void test(atomic_memory_order order) { + T zero = 0; + T five = 5; + T ten = 10; + + // Failed cmpxchg: compare_value does not match. + AtomicAccess::store(&_test_value, zero); + T res = AtomicAccess::cmpxchg(&_test_value, five, ten, order); + EXPECT_EQ(zero, res); + EXPECT_EQ(zero, AtomicAccess::load(&_test_value)); + + // Successful cmpxchg: compare_value matches. + res = AtomicAccess::cmpxchg(&_test_value, zero, ten, order); + EXPECT_EQ(zero, res); + EXPECT_EQ(ten, AtomicAccess::load(&_test_value)); + } +}; + +TEST_VM(AtomicAccessOrderedCmpxchgTest, int8) { + using Support = AtomicAccessOrderedCmpxchgTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test(order); + } +} + +TEST_VM(AtomicAccessOrderedCmpxchgTest, int32) { + using Support = AtomicAccessOrderedCmpxchgTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test(order); + } +} + +TEST_VM(AtomicAccessOrderedCmpxchgTest, int64) { + using Support = AtomicAccessOrderedCmpxchgTestSupport; + for (atomic_memory_order order : memory_orders) { + Support().test(order); + } +} + +template +struct AtomicAccessOrderedLoadStoreTestSupport { + volatile T _test_value; + + AtomicAccessOrderedLoadStoreTestSupport() : _test_value{} {} + + void test_release_store_load_acquire(T value) { + AtomicAccess::release_store(&_test_value, value); + T loaded = AtomicAccess::load_acquire(&_test_value); + EXPECT_EQ(value, loaded); + } + + void test_release_store_fence(T value) { + AtomicAccess::release_store_fence(&_test_value, value); + T loaded = AtomicAccess::load_acquire(&_test_value); + EXPECT_EQ(value, loaded); + } +}; + +TEST_VM(AtomicAccessOrderedLoadStoreTest, int8) { + using Support = AtomicAccessOrderedLoadStoreTestSupport; + Support().test_release_store_load_acquire(42); + Support().test_release_store_fence(42); +} + +TEST_VM(AtomicAccessOrderedLoadStoreTest, int16) { + using Support = AtomicAccessOrderedLoadStoreTestSupport; + Support().test_release_store_load_acquire(1234); + Support().test_release_store_fence(1234); +} + +TEST_VM(AtomicAccessOrderedLoadStoreTest, int32) { + using Support = AtomicAccessOrderedLoadStoreTestSupport; + Support().test_release_store_load_acquire(123456); + Support().test_release_store_fence(123456); +} + +TEST_VM(AtomicAccessOrderedLoadStoreTest, int64) { + using Support = AtomicAccessOrderedLoadStoreTestSupport; + Support().test_release_store_load_acquire(1234567890LL); + Support().test_release_store_fence(1234567890LL); +} + +TEST_VM(AtomicAccessOrderedLoadStoreTest, ptr) { + int dummy[10] = {}; + using Support = AtomicAccessOrderedLoadStoreTestSupport; + Support().test_release_store_load_acquire(&dummy[5]); + Support().test_release_store_fence(&dummy[7]); +} diff --git a/test/hotspot/gtest/runtime/test_globals.cpp b/test/hotspot/gtest/runtime/test_globals.cpp index e88f930ff731..dab80ca3d5a3 100644 --- a/test/hotspot/gtest/runtime/test_globals.cpp +++ b/test/hotspot/gtest/runtime/test_globals.cpp @@ -58,7 +58,7 @@ TEST_VM(FlagGuard, size_t_flag) { } TEST_VM(FlagGuard, uint64_t_flag) { - TEST_FLAG(ErrorLogTimeout, uint64_t, 1337); + TEST_FLAG(MaxDirectMemorySize, uint64_t, 4294967297); } TEST_VM(FlagGuard, double_flag) { diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index a4308c7ea301..2eca4b5cddd2 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -87,11 +87,7 @@ gc/stress/jfr/TestStressAllocationGCEventsWithShenandoah.java#generational 83869 gc/stress/jfr/TestStressAllocationGCEventsWithShenandoah.java#default 8386964 generic-all gc/stress/jfr/TestStressBigAllocationGCEventsWithShenandoah.java#generational 8386964 generic-all gc/stress/jfr/TestStressBigAllocationGCEventsWithShenandoah.java#default 8386964 generic-all -gc/TestGCALotAtAllSafepoints.java#Parallel 8390661 generic-all -gc/TestGCALotAtAllSafepoints.java#Serial 8390661 generic-all -gc/TestGCALotAtAllSafepoints.java#G1 8390661 generic-all -gc/TestGCALotAtAllSafepoints.java#Z 8390661 generic-all -gc/TestGCALotAtAllSafepoints.java#Shenandoah 8390661 generic-all +gc/metaspace/TestMetaspaceFirstGC.java 8391711 generic-all ############################################################################# @@ -107,7 +103,6 @@ runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x -runtime/Thread/TestAlwaysPreTouchStacks.java 8383372 macosx-aarch64 applications/jcstress/copy.java 8229852 linux-all @@ -142,6 +137,8 @@ serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStr serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java 8385679 generic-all +serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java 8390812 windows-x64 + ############################################################################# # :hotspot_misc @@ -158,11 +155,6 @@ serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java 8385679 generic- vmTestbase/gc/gctests/FinalizeTest04/FinalizeTest04.java 8284234 generic-all vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java 8284234 generic-all -vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all -vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all -vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8208250 generic-all -vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8208250 generic-all - vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 8073470 linux-all vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t006/TestDescription.java 8372206 generic-all vmTestbase/nsk/jvmti/InterruptThread/intrpthrd003/TestDescription.java 8288911 macosx-all diff --git a/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java b/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java index 99cf06110d67..068a72914771 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java +++ b/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @key stress randomness - * @bug 8252219 8256535 8317349 8319879 8335334 8325478 8387940 + * @bug 8252219 8256535 8317349 8319879 8335334 8325478 8387940 8391439 * @requires vm.compiler2.enabled * @summary Tests that different combinations of stress options and * -XX:StressSeed=N are accepted. @@ -64,6 +64,8 @@ * compiler.arguments.TestStressOptions * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressEliminateAllocations -XX:StressSeed=42 * compiler.arguments.TestStressOptions + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+StressVerifyMeetJoin + * ${test.main.class} */ package compiler.arguments; diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestCloneMemBarKind.java b/test/hotspot/jtreg/compiler/arraycopy/TestCloneMemBarKind.java new file mode 100644 index 000000000000..520a81ff3842 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestCloneMemBarKind.java @@ -0,0 +1,67 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.arraycopy; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8379228 + * @summary Verify that the trailing MemBar after clone expansion is marked as TrailingExpandedArrayCopy. + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver ${test.main.class} + */ +public class TestCloneMemBarKind { + + public static void main(String[] args) { + TestFramework.run(); + } + + // More than 8 (=ArrayCopyLoadStoreMaxElem) fields so the clone is expanded + // as an arraycopy stub call (is_clonebasic), not as inline loads/stores. + static class BigObj implements Cloneable { + int i1, i2, i3, i4, i5, i6, i7, i8, i9; + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } + + static BigObj src = new BigObj(); + + @Test + @IR(applyIf = {"ArrayCopyLoadStoreMaxElem", "< 9"}, + phase = CompilePhase.AFTER_MACRO_EXPANSION, + counts = {"MemBar.*TrailingExpandedArrayCopy", ">= 1"}) + static Object testClone() throws CloneNotSupportedException { + return src.clone(); + } + + @Run(test = "testClone") + void runner() throws CloneNotSupportedException { + src.i1 = 42; + testClone(); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/Test6857159.java b/test/hotspot/jtreg/compiler/c2/Test6857159.java deleted file mode 100644 index c60192643e9e..000000000000 --- a/test/hotspot/jtreg/compiler/c2/Test6857159.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 6857159 - * @summary local schedule failed with checkcast of Thread.currentThread() - * @library /test/lib - * @modules java.base/jdk.internal.misc - * - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xbatch -XX:CompileCommand=compileonly,compiler.c2.Test6857159$ct0::run - * compiler.c2.Test6857159 - */ - -package compiler.c2; - -import jdk.test.whitebox.WhiteBox; - -public class Test6857159 extends Thread { - public static void main(String[] args) throws Exception { - var whiteBox = WhiteBox.getWhiteBox(); - var method = ct0.class.getDeclaredMethod("run"); - for (int i = 0; i < 20000; i++) { - Thread t = null; - switch (i % 3) { - case 0: - t = new ct0(); - break; - case 1: - t = new ct1(); - break; - case 2: - t = new ct2(); - break; - } - t.start(); - t.join(); - } - if (!whiteBox.isMethodCompiled(method)) { - throw new AssertionError(method + " didn't get compiled"); - } - } - - static class ct0 extends Test6857159 { - public void message() { } - - public void run() { - message(); - ct0 ct = (ct0) Thread.currentThread(); - ct.message(); - } - } - - static class ct1 extends ct0 { - public void message() { } - } - - static class ct2 extends ct0 { - public void message() { } - } -} diff --git a/test/hotspot/jtreg/compiler/c2/TestLoadKlassAntiDep.java b/test/hotspot/jtreg/compiler/c2/TestLoadKlassAntiDep.java new file mode 100644 index 000000000000..1582ede7d050 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestLoadKlassAntiDep.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. + * 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 6857159 + * @summary local schedule failed with checkcast of Thread.currentThread() + * @modules java.base/jdk.internal.access + * @run main ${test.main.class} + * @run main/othervm -Xbatch + * -XX:CompileCommand=compileonly,${test.main.class}::test + * -XX:CompileCommand=dontinline,${test.main.class}::notInlined + * ${test.main.class} + */ + +package compiler.c2; + +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.SharedSecrets; + +public class TestLoadKlassAntiDep { + private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + + public static void main(String[] args) { + for (int i = 0; i < 50_000; i++) { + test(); + } + } + + static void notInlined() { } + + static Class test() { + notInlined(); + + // These intrinsics create immutable klass loads whose addresses depend on the carrier thread load + return JLA.currentCarrierThread().getClass().getSuperclass(); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/TestSpilledUncommonTrapRequest.java b/test/hotspot/jtreg/compiler/c2/TestSpilledUncommonTrapRequest.java new file mode 100644 index 000000000000..74ba57086668 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestSpilledUncommonTrapRequest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8358889 + * @summary Test that a spilled uncommon trap request is handled properly. + * @requires vm.compiler2.enabled + * @library /test/lib + * @run main ${test.main.class} + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp + * -XX:StressSeed=403 -XX:+StressGCM + * -XX:CompileCommand=compileonly,${test.main.class}::test + * -XX:CompileCommand=dontinline,${test.main.class}::dontInline + * ${test.main.class} + */ + +import jdk.test.lib.Asserts; + +public class TestSpilledUncommonTrapRequest { + static long sum; + static final int[] array = new int[64]; + + static int max(int first, int second) { + return first > second ? first : second; + } + + static int dontInline() { + return 42; + } + + static void test(double[][] doubles) { + // Vectorize a loop such that Compile::current()->max_vector_size() > 0 holds + for (int i = 0; i < 64; i++) { + array[i] = i; + } + + // C2 adds an uncommon trap with 'Reason_null_check == 1' and 'Action_maybe_recompile == 1' for the + // null-check of the inner array doubles[0] here. This is encoded as + // ~((reason << 3) + action) = ~((1 << 3) + 1) = ~9 = -10 + // which is then shared with the explicit constant -10 passed as argument here. + doubles[0][0] = max(dontInline(), -10); + + // Keep the shared -10 live in a loop phi and create enough register pressure for RA to spill it. + int product = -10; + for (int i = 0; i < 64; i++) { + product *= 79; + sum++; + array[i] = 0; + } + sum += product; + } + + public static void main(String[] args) { + test(new double[1][1]); + Asserts.assertEQ(sum, 1573390390L); + } +} + diff --git a/test/hotspot/jtreg/compiler/codecache/ExitOnFullCodeCacheTest.java b/test/hotspot/jtreg/compiler/codecache/ExitOnFullCodeCacheTest.java new file mode 100644 index 000000000000..d69384e8de02 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codecache/ExitOnFullCodeCacheTest.java @@ -0,0 +1,91 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8376286 + * @summary With -XX:+ExitOnFullCodeCache the VM must terminate cleanly when the + * code cache fills up, instead of asserting "Possible safepoint reached + * by thread that does not allow it" when the exit is initiated from a + * compiler thread while it is installing an nmethod. + * @requires vm.debug == true & vm.compMode != "Xint" + * @comment ExitOnFullCodeCache is a develop flag, so it is only available in a + * debug VM. The assertion it used to trigger only exists in debug too. + * @library /test/lib + * @run driver compiler.codecache.ExitOnFullCodeCacheTest + */ + +package compiler.codecache; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class ExitOnFullCodeCacheTest { + + // Assertion message that used to be triggered by JDK-8376286. + private static final String SAFEPOINT_ASSERT = + "Possible safepoint reached by thread that does not allow it"; + + // Non-method code heap size, in KB. It must be large enough to hold all of + // the VM-internal (non-method) code, and large enough that the reserved + // code cache is big enough for compilation to start (smaller values were + // observed not to overflow the code cache at startup at all). + private static final long NON_NMETHOD_KB = 512000; // 500 MB + + // Margin left for the profiled + non-profiled (+ hot) nmethod heaps, in KB. + // Each of those heaps must be at least the platform minimum, which equals + // the largest allocation/page granularity across supported platforms + // (64 KB). With up to three such heaps, 3 * 64 KB = 192 KB is the minimum; + // 256 KB (a multiple of 64 KB) keeps the code heap sizes valid on 4K/16K/64K + // granularity platforms while still leaving the nmethod heaps small enough + // (~128 KB) that the very first nmethod installation on a compiler thread + // fails and triggers the ExitOnFullCodeCache path while the thread is inside + // nmethod::new_nmethod (a no-safepoint region). Before the fix this asserted. + private static final long NMETHOD_HEAPS_MARGIN_KB = 256; + + public static void main(String[] args) throws Exception { + long reservedKB = NON_NMETHOD_KB + NMETHOD_HEAPS_MARGIN_KB; + + OutputAnalyzer oa = ProcessTools.executeLimitedTestJava( + "-Xcomp", + "-XX:+ExitOnFullCodeCache", + "-XX:NonNMethodCodeHeapSize=" + NON_NMETHOD_KB + "K", + "-XX:ReservedCodeCacheSize=" + reservedKB + "K", + // SapMachine 2025-12-10 We don't get exact matches when rounding to large page sizes. + "-XX:-UseLargePages", + "-version"); + + // The invariant that must always hold, on every platform, is that the + // exit initiated from the compiler thread does not reach the assertion. + oa.shouldNotContain(SAFEPOINT_ASSERT); + oa.shouldNotContain("A fatal error has been detected"); + + // Guard against a silent no-op: if the chosen sizes are not valid on + // this platform's granularity, the VM aborts during initialization + // (e.g. "Invalid code heap sizes") without ever exercising the exit + // path, which would make the test pass without testing anything. Fail + // loudly in that case instead. + oa.shouldNotContain("Invalid code heap sizes"); + oa.shouldNotContain("Error occurred during initialization of VM"); + } +} diff --git a/test/hotspot/jtreg/compiler/compilercontrol/commands/CompileLevelPrintTest.java b/test/hotspot/jtreg/compiler/compilercontrol/commands/CompileLevelPrintTest.java index dcf625c807b3..340c55ef99c3 100644 --- a/test/hotspot/jtreg/compiler/compilercontrol/commands/CompileLevelPrintTest.java +++ b/test/hotspot/jtreg/compiler/compilercontrol/commands/CompileLevelPrintTest.java @@ -26,11 +26,13 @@ * @test * @bug 8313713 * @summary Test -XX:CompileCommand=exclude and compileonly with different compilation levels, - * monitoring compilation events in VM -XX:+PrintCompilation and -XX:+PrintTieredEvents output + * monitoring compilation events in VM -XX:+PrintCompilation output * @requires vm.compMode != "Xint" & vm.flavor == "server" * & (vm.opt.TieredStopAtLevel == 4 | vm.opt.TieredStopAtLevel == null) * & (vm.opt.CompilationMode == "normal" | vm.opt.CompilationMode == null) * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main ${test.main.class} runner */ @@ -39,6 +41,7 @@ import jdk.test.lib.Asserts; import jdk.test.lib.management.InputArguments; import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -58,7 +61,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BooleanSupplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -80,6 +82,7 @@ public class CompileLevelPrintTest { static final String TEST_METHOD_SIGNATURE = TEST_METHOD_NAME_DBL_COLON + "("; static final String TESTEE_WAITING_FOR_START_CMD = "==> waiting for start command"; + static final String TESTEE_WAITING_FOR_STOP_CMD = "==> waiting for stop command"; static final String START_CMD = "start"; static final String STOP_CMD = "stop"; @@ -90,8 +93,8 @@ public class CompileLevelPrintTest { static class TesteeState { final CountDownLatch waitingForStartTest = new CountDownLatch(1); - final AtomicInteger compiler1QueueSize = new AtomicInteger(); - final AtomicInteger compiler2QueueSize = new AtomicInteger(0); + volatile boolean readyForStartTest; + volatile boolean readyForStopTest; final Set compileCommandsReported = Collections.synchronizedSet(new HashSet<>()); volatile Set testMethodCompiledAtLevel = Collections.synchronizedSet(new HashSet<>()); final Set testMethodExcludedAtLevel = Collections.synchronizedSet(new HashSet<>()); @@ -161,9 +164,6 @@ static class Runner { private static final Pattern reCompileCommand = Pattern.compile( "CompileCommand: (.*)"); - private static final Pattern reTieredEvent = Pattern.compile( - "[0-9.]+: \\[(call|loop|compile|force-compile|remove-from-queue|update-in-queue|reprofile|make-not-entrant) " - + "level=\\d \\[([^]]+)] @-?\\d+ queues=(\\d+),(\\d+).*]"); private static final Pattern reCompilation = Pattern.compile( "(\\d+) (C1|C2|no compiler): *(\\d+) ([ %][ s][ !][ b][ n]) ([-0-4 ]) +([^ ]+).*"); private static final Pattern reExcludeCompile = Pattern.compile( @@ -189,9 +189,10 @@ public static void run(String compileCmd, ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:.", "-XX:+PrintCompilation", "-XX:+CIPrintCompilerName", - "-XX:+PrintTieredEvents", "-XX:+LogVMOutput", "-XX:+LogCompilation", "-XX:" + (tieredCompilation ? "+" : "-") + "TieredCompilation", @@ -215,14 +216,10 @@ public static void run(String compileCmd, matchTesteeMessages(processErrOut, testeeState, "testee-" + process.pid() + ".err")); IO.println("##> Waiting for testee to get ready for the start command"); - if (!testeeState.waitingForStartTest.await(TIMEOUT_SEC, TimeUnit.SECONDS)) { - throw new RuntimeException("No start signal from testee"); - } + testeeState.waitingForStartTest.await(); + Asserts.assertTrue(testeeState.readyForStartTest, + "Testee exited before signaling readiness"); - Asserts.assertTrue(waitUntil(() -> !process.isAlive() - || (testeeState.compiler1QueueSize.get() < 5 - && testeeState.compiler2QueueSize.get() < 5)), - "Compiler queue is still not empty"); Asserts.assertTrue(testeeState.compileCommandsReported.contains( compileCmd + " " + TEST_METHOD_NAME_DOT + " intx " + compileCmd + " = " + cmdCompLevel), "'CompileCommand: " + compileCmd + "...' was not printed"); @@ -234,6 +231,7 @@ public static void run(String compileCmd, processInput.write(START_CMD); processInput.newLine(); processInput.flush(); waitUntil(() -> !process.isAlive() + || testeeState.readyForStopTest || (!expectedCompLevel.isEmpty() && !expectExcludedAtLevels.isEmpty() && expectedCompLevel.equals(testeeState.testMethodCompiledAtLevel) && expectedCompLevel.equals(testeeState.testMethodPrintedAtLevel) @@ -311,17 +309,7 @@ private static void matchVmMessages(BufferedReader testeeOutput, TesteeState tes msg = "Compile command reported: " + matcher.group(1); - } else if ((matcher = reTieredEvent.matcher(line)).matches()) { - testeeState.compiler1QueueSize.set(Integer.parseInt(matcher.group(3))); - testeeState.compiler2QueueSize.set(Integer.parseInt(matcher.group(4))); - } else if ((matcher = reCompilation.matcher(line)).matches()) { - if ("C1".equalsIgnoreCase(matcher.group(2))) { - testeeState.compiler1QueueSize.decrementAndGet(); - } else { - testeeState.compiler2QueueSize.decrementAndGet(); - } - if (matcher.group(6).contains(TEST_METHOD_NAME_DBL_COLON)) { testeeState.testMethodCompiledAtLevel.add(matcher.group(5)); @@ -390,7 +378,11 @@ private static void matchTesteeMessages(BufferedReader testeeErrorOutput, Testee if (TESTEE_WAITING_FOR_START_CMD.equals(line)) { IO.println("##> Testee is waiting for start command"); + testeeState.readyForStartTest = true; testeeState.waitingForStartTest.countDown(); + } else if (TESTEE_WAITING_FOR_STOP_CMD.equals(line)) { + IO.println("##> Testee is waiting for stop command"); + testeeState.readyForStopTest = true; } else if (line.startsWith("==>")) { IO.println(line); } else if (line.startsWith("Exception in thread ") || line.startsWith("at ")) { @@ -401,11 +393,15 @@ private static void matchTesteeMessages(BufferedReader testeeErrorOutput, Testee } } catch (Exception ex) { ex.printStackTrace(); + } finally { + // Unblock the runner if the testee exits before signaling readiness. + testeeState.waitingForStartTest.countDown(); } } } static class Testee { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final CountDownLatch startCmd = new CountDownLatch(1); private static final CountDownLatch stopCmd = new CountDownLatch(1); @@ -419,12 +415,12 @@ static void run() throws IOException, InterruptedException { return; } - // Print 3 times, since the output can be intermixed with + Asserts.assertTrue(waitUntil(() -> WB.getCompileQueuesSize() == 0), + "Compiler queue is still not empty"); + + // Signal readiness after the compiler queues have drained, then wait for the runner. System.err.println(TESTEE_WAITING_FOR_START_CMD); - if (!startCmd.await(TIMEOUT_SEC + 1, TimeUnit.SECONDS)) { - System.err.println("==> 'start' command was not given in stdin"); - return; - } + startCmd.await(); if (stopCmd.getCount() == 0) { return; @@ -432,6 +428,10 @@ static void run() throws IOException, InterruptedException { System.err.println("==> starting test"); runTestCode(); + + // Keep the input pipe open until the runner has consumed the required output. + System.err.println(TESTEE_WAITING_FOR_STOP_CMD); + stopCmd.await(); } finally { System.err.println("==> exiting testee()"); } diff --git a/test/hotspot/jtreg/compiler/debug/TestStressBailout.java b/test/hotspot/jtreg/compiler/debug/TestStressBailout.java index f79cb679c413..64f023388e92 100644 --- a/test/hotspot/jtreg/compiler/debug/TestStressBailout.java +++ b/test/hotspot/jtreg/compiler/debug/TestStressBailout.java @@ -50,6 +50,16 @@ * @run main compiler.debug.TestStressBailout -XX:VerifyIterativeGVN=1111 */ +/* + * @test + * @key stress randomness + * @bug 8390121 + * @requires vm.debug == true & vm.compiler2.enabled & (vm.opt.AbortVMOnCompilationFailure == "null" | !vm.opt.AbortVMOnCompilationFailure) + * @summary Bailouts between optimization phases must not reach IGVN verification + * @library /test/lib / + * @run main ${test.main.class} -XX:VerifyIterativeGVN=1110 -XX:+StressIGVN -XX:+StressIncrementalInlining + */ + public class TestStressBailout { static void runTest(int invprob, Stream vmArgs) throws Exception { diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestCopyOfBrokenAntiDependency.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestCopyOfBrokenAntiDependency.java index 508d50723695..6c3c5ab6af3d 100644 --- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestCopyOfBrokenAntiDependency.java +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestCopyOfBrokenAntiDependency.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +24,14 @@ /** * @test - * @bug 8238384 - * @summary CTW: C2 compilation fails with "assert(store != load->find_exact_control(load->in(0))) failed: dependence cycle found" - * - * @run main/othervm -XX:-BackgroundCompilation TestCopyOfBrokenAntiDependency - * + * @bug 8238384 8391160 + * @summary Test that Arrays.copyOf with non-escaping allocations and distinct memory slices compiles without assertion failures + * @run main/othervm -Xbatch ${test.main.class} + * @run main/othervm -Xbatch -XX:-ReduceInitialCardMarks -XX:-ReduceBulkZeroing ${test.main.class} */ +package compiler.escapeAnalysis; + import java.util.Arrays; public class TestCopyOfBrokenAntiDependency { diff --git a/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java b/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java index bcc3b9541ba5..b28cbca40142 100644 --- a/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java +++ b/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/inlining/TestLateInlineNullableReceiver.java b/test/hotspot/jtreg/compiler/inlining/TestLateInlineNullableReceiver.java new file mode 100644 index 000000000000..bd6ce98658b9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/inlining/TestLateInlineNullableReceiver.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8387799 + * @summary Test that a nullable receiver is not endlessly retried for virtual late inlining + * @modules jdk.incubator.vector + * @library /test/lib + * @requires vm.compiler2.enabled + * @run main ${test.main.class} + * @run main/othervm -Xcomp + * -XX:CompileCommand=compileonly,${test.main.class}::test + * -XX:CompileCommand=delayinline,${test.main.class}::lateInlined + * ${test.main.class} + */ + +package compiler.inlining; + +import jdk.incubator.vector.FloatVector; +import jdk.incubator.vector.IntVector; +import jdk.incubator.vector.LongVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.test.lib.Asserts; + +public class TestLateInlineNullableReceiver { + static final VectorMask MASK = FloatVector.SPECIES_128.maskAll(true); + // Another (unused) mask to prevent dervirtualization of the 'trueCount' call + static final VectorMask OTHER_MASK = FloatVector.SPECIES_64.maskAll(true); + + static VectorMask lateInlined(Object value) { + return (VectorMask) MASK.getClass().cast(value); + } + + static int test(Object value) { + // XOR a vector and make sure it's live at below virtual call + IntVector vector = IntVector.fromArray(IntVector.SPECIES_128, new int[4], 0).lanewise(VectorOperators.XOR, 0); + + // After late inlining, 'value' is exact but still nullable. C2 will then + // attempt to strength reduce the 'trueCount' virtual call to a static call. + int result = lateInlined(value).trueCount(); + + return result + vector.lane(0); // Keep the vector live + } + + public static void main(String[] args) { + for (int i = 0; i < 200; i++) { + Asserts.assertEquals(test(MASK), 4); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestAntiDependency.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestAntiDependency.java new file mode 100644 index 000000000000..341396e56dd7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestAntiDependency.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.intrinsics.string; + +import compiler.lib.ir_framework.DontInline; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.Test; +import compiler.lib.ir_framework.TestFramework; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import jdk.test.lib.Asserts; + +/* + * @test + * @bug 8373591 + * @summary Verify that StringLatin1::inflate, StringUTF16::compress, and + * StringCoding::implEncodeAsciiArray are scheduled properly + * @library /test/lib / + * @modules java.base/java.lang:+open + * @run driver ${test.main.class} + */ +public class TestAntiDependency { + static final MethodHandle COMPRESS_HANDLE; + static final MethodHandle INFLATE_HANDLE; + static final MethodHandle ENCODE_ISO_HANDLE; + static { + try { + var currentLookup = MethodHandles.lookup(); + var stringLookup = MethodHandles.privateLookupIn(String.class, currentLookup); + Class stringUtf16Class = stringLookup.findClass("java.lang.StringUTF16"); + var stringUtf16Lookup = MethodHandles.privateLookupIn(stringUtf16Class, currentLookup); + COMPRESS_HANDLE = stringUtf16Lookup.findStatic(stringUtf16Class, "compress0", + MethodType.methodType(int.class, char[].class, int.class, byte[].class, int.class, int.class)); + Class stringLatin1Class = stringLookup.findClass("java.lang.StringLatin1"); + var stringLatin1Lookup = MethodHandles.privateLookupIn(stringLatin1Class, currentLookup); + INFLATE_HANDLE = stringLatin1Lookup.findStatic(stringLatin1Class, "inflate0", + MethodType.methodType(void.class, byte[].class, int.class, char[].class, int.class, int.class)); + Class stringCodingClass = stringLookup.findClass("java.lang.StringCoding"); + ENCODE_ISO_HANDLE = stringLookup.findStatic(stringCodingClass, "encodeAsciiArray0", + MethodType.methodType(int.class, char[].class, int.class, byte[].class, int.class, int.class)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + var testFramework = new TestFramework(); + testFramework.setDefaultWarmup(1); + testFramework.addFlags("--add-opens=java.base/java.lang=ALL-UNNAMED"); + testFramework.start(); + } + + @DontInline + static void consume(Object o1, Object o2) {} + + @Test + static int testStringCompress() throws Throwable { + byte[] dst = new byte[4]; + char[] src = new char[4]; + consume(dst, src); + dst[0] = (byte) -1; + + // The compiler must not schedule this after the store to src, either by having + // StringCompressedCopyNode kill the whole memory, or by taking into consideration the + // anti-dependency between 2 nodes + int _ = (int) COMPRESS_HANDLE.invokeExact(src, 0, dst, 0, 4); + src[0] = 1; + return dst[0]; + } + + @Test + static int testStringInflate() throws Throwable { + char[] dst = new char[4]; + byte[] src = new byte[4]; + consume(dst, src); + dst[0] = (char) -1; + + // The compiler must not schedule this after the store to src, either by having + // StringInflatedCopyNode kill the whole memory, or by taking into consideration the + // anti-dependency between 2 nodes + INFLATE_HANDLE.invokeExact(src, 0, dst, 0, 4); + src[0] = 1; + return dst[0]; + } + + @Test + static int testEncodeISO() throws Throwable { + byte[] dst = new byte[4]; + char[] src = new char[4]; + consume(dst, src); + dst[0] = (byte) -1; + + // The compiler must not schedule this after the store to src, either by having + // EncodeISOArrayNode kill the whole memory, or by taking into consideration the + // anti-dependency between 2 nodes + int _ = (int) ENCODE_ISO_HANDLE.invokeExact(src, 0, dst, 0, 4); + src[0] = 1; + return dst[0]; + } + + @Run(test = {"testStringCompress", "testStringInflate", "testEncodeISO"}) + public void run() throws Throwable { + Asserts.assertEQ(0, testStringCompress()); + Asserts.assertEQ(0, testStringInflate()); + Asserts.assertEQ(0, testEncodeISO()); + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/zip/TestFpRegsABI.java b/test/hotspot/jtreg/compiler/intrinsics/zip/TestFpRegsABI.java index 46ecb64096b8..3a3c8b2765d8 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/zip/TestFpRegsABI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/zip/TestFpRegsABI.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 6fad572fd37f..510c9f7ef369 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1885,6 +1885,11 @@ public static void anyLoadOfNodes(String irNodePlaceholder, String fieldHolder) parsePredicateNodes(AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "Auto_Vectorization_Check"); } + public static final String SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE = PREFIX + "SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE" + POSTFIX; + static { + parsePredicateNodes(SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "Short_Running_Long_Loop"); + } + public static final String PREDICATE_TRAP = PREFIX + "PREDICATE_TRAP" + POSTFIX; static { trapNodes(PREDICATE_TRAP, "predicate"); @@ -2808,6 +2813,56 @@ public static void anyStoreOfNodes(String irNodePlaceholder, String fieldHolder) machOnlyNameRegex(VMASK_AND_NOT_L, "vmask_and_notL"); } + public static final String RISCV_VMASK_OR_NOT_I = PREFIX + "RISCV_VMASK_OR_NOT_I" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_OR_NOT_I, "vmask_or_notI"); + } + + public static final String RISCV_VMASK_OR_NOT_L = PREFIX + "RISCV_VMASK_OR_NOT_L" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_OR_NOT_L, "vmask_or_notL"); + } + + public static final String RISCV_VMASK_NAND_I = PREFIX + "RISCV_VMASK_NAND_I" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NAND_I, "vmask_nandI"); + } + + public static final String RISCV_VMASK_NAND_L = PREFIX + "RISCV_VMASK_NAND_L" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NAND_L, "vmask_nandL"); + } + + public static final String RISCV_VMASK_NOR_I = PREFIX + "RISCV_VMASK_NOR_I" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NOR_I, "vmask_norI"); + } + + public static final String RISCV_VMASK_NOR_L = PREFIX + "RISCV_VMASK_NOR_L" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NOR_L, "vmask_norL"); + } + + public static final String RISCV_VMASK_XNOR_I = PREFIX + "RISCV_VMASK_XNOR_I" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_XNOR_I, "vmask_xnorI"); + } + + public static final String RISCV_VMASK_XNOR_L = PREFIX + "RISCV_VMASK_XNOR_L" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_XNOR_L, "vmask_xnorL"); + } + + public static final String RISCV_VMASK_NOT_I = PREFIX + "RISCV_VMASK_NOT_I" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NOT_I, "vmask_notI"); + } + + public static final String RISCV_VMASK_NOT_L = PREFIX + "RISCV_VMASK_NOT_L" + POSTFIX; + static { + machOnlyNameRegex(RISCV_VMASK_NOT_L, "vmask_notL"); + } + public static final String VMLA = PREFIX + "VMLA" + POSTFIX; static { machOnlyNameRegex(VMLA, "vmla"); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java b/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java index 902e2d54774e..4d5961a19fee 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,8 +44,8 @@ public class RunInfo extends AbstractInfo { private final boolean hasMultipleTests; public RunInfo(List tests) { - super(tests.get(0).getTestMethod().getDeclaringClass()); - this.test = tests.get(0); + super(tests.getFirst().getTestMethod().getDeclaringClass()); + this.test = tests.getFirst(); this.testMethod = test.getTestMethod(); this.hasMultipleTests = tests.size() != 1; if (hasMultipleTests) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java index 014a65efc793..aeda075280bd 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java @@ -97,11 +97,13 @@ public Scenario(int index, String... flags) { * Add additional VM flags to this scenario. * * @param flags the additional scenario VM flags. + * @return the scenario object. */ - public void addFlags(String... flags) { + public Scenario addFlags(String... flags) { if (flags != null) { this.flags.addAll(Arrays.asList(flags)); } + return this; } /** diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 2076b9cf0889..6fe4b31b9ef0 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -158,7 +158,7 @@ public class TestFramework { public static final boolean VERBOSE = Boolean.getBoolean("Verbose"); public static final boolean PRINT_RULE_MATCHING_TIME = Boolean.getBoolean("PrintRuleMatchingTime"); private static final boolean TEST_LIST_IS_EMPTY = SystemProperty.getTestList().isEmpty(); - private static final boolean EXCLUDE_LIST_IS_EMPTY = SystemProperty.getExcludeList().isEmpty();; + private static final boolean EXCLUDE_LIST_IS_EMPTY = SystemProperty.getExcludeList().isEmpty(); private static final boolean REPORT_STDOUT = Boolean.getBoolean("ReportStdout"); // Only used for internal testing and should not be used for normal user testing. @@ -801,7 +801,7 @@ private void reportScenarioFailures(Map exceptionMap) { private static String getScenarioTitleAndFlags(Scenario scenario) { StringBuilder builder = new StringBuilder(); String title = "Scenario #" + scenario.getIndex(); - builder.append(title).append(System.lineSeparator()).append("=".repeat(title.length())) + builder.append(title).append(System.lineSeparator()).repeat("=", title.length()) .append(System.lineSeparator()); builder.append("Scenario flags: [").append(String.join(", ", scenario.getFlags())).append("]") .append(System.lineSeparator()); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index baed93594597..c77951755025 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -110,12 +110,16 @@ private TestVMData processTestVmResult(TestFrameworkSocket socket, boolean allow */ private void dumpTestVmOutputIfRequested() { if (DUMP_OUTPUT) { - System.out.println("Test VM Output"); - System.out.println("--------------"); - System.out.println(oa.getOutput()); + dumpTestVmOutput(); } } + private void dumpTestVmOutput() { + System.out.println("Test VM Output"); + System.out.println("--------------"); + System.out.println(oa.getOutput()); + } + private TestVMData readAndDumpTestVmData(TestFrameworkSocket socket, boolean allowNotCompilable) { String hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid()); TestVMData testVMData = socket.testVmData(hotspotPidFileName, allowNotCompilable); @@ -154,7 +158,8 @@ private TestVMException createTestVMExceptionForNonZeroExit(TestFrameworkSocket secondaryException = buildSecondaryExceptionInfo(e); } // Primary exception: non-zero Test VM exit. - return new TestVMException(buildExceptionInfo() + secondaryException); + String exceptionInfo = buildPrimaryExceptionInfo() + secondaryException; + return new TestVMException(exceptionInfo); } private String buildSecondaryExceptionInfo(RuntimeException e) { @@ -172,7 +177,7 @@ private String buildSecondaryExceptionInfo(RuntimeException e) { /** * Get more detailed information about the exception in a pretty format. */ - private String buildExceptionInfo() { + private String buildPrimaryExceptionInfo() { StringBuilder builder = new StringBuilder(); builder.append("Test VM exited with code ").append(oa.getExitValue()).append(System.lineSeparator()); if (hasFatalErrorMarker() || DUMP_OUTPUT) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessageParser.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessageParser.java index 5b0c624720a2..0789009b2936 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessageParser.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessageParser.java @@ -45,8 +45,8 @@ public class JavaMessageParser implements TestVmMessageParser { private static final Pattern TAG_PATTERN = Pattern.compile("^(\\[[^]]+])\\s*(.*)$"); private final List stdoutMessages; - private final List executedTests; private final Map methodTimes; + private final List executedTests; private final MultiLineParser vmInfoParser; private final MultiLineParser applicableIRRulesParser; @@ -100,11 +100,12 @@ private void parseTagLine(Matcher tagLineMatcher) { } private void parsePrintTimes(String message) { - String[] split = message.split(","); - TestFramework.check(split.length == 2, "unexpected format"); - String methodName = split[0]; + // When using @Run with multiple tests, we could have several commas in the message + int lastCommaIndex = message.lastIndexOf(','); + TestFramework.check(lastCommaIndex > 0 && lastCommaIndex < message.length() - 1, "unexpected format"); + String methodName = message.substring(0, lastCommaIndex); try { - long duration = Long.parseLong(split[1]); + long duration = Long.parseLong(message.substring(lastCommaIndex + 1)); methodTimes.put(methodName, duration); } catch (NumberFormatException e) { throw new TestFrameworkException("invalid duration", e); @@ -123,8 +124,8 @@ private void parseEndTag() { @Override public JavaMessages output() { return new JavaMessages(new StdoutMessages(stdoutMessages), - new ExecutedTests(executedTests), new MethodTimes(methodTimes), + new ExecutedTests(executedTests), applicableIRRulesParser.output(), vmInfoParser.output()); } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessages.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessages.java index e817610f4410..c7380205974e 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessages.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/JavaMessages.java @@ -28,16 +28,16 @@ */ public class JavaMessages { private final StdoutMessages stdoutMessages; - private final ExecutedTests executedTests; private final MethodTimes methodTimes; + private final ExecutedTests executedTests; private final ApplicableIRRules applicableIrRules; private final VMInfo vmInfo; - JavaMessages(StdoutMessages stdoutMessages, ExecutedTests executedTests, MethodTimes methodTimes, + JavaMessages(StdoutMessages stdoutMessages, MethodTimes methodTimes, ExecutedTests executedTests, ApplicableIRRules applicableIrRules, VMInfo vmInfo) { this.stdoutMessages = stdoutMessages; - this.executedTests = executedTests; this.methodTimes = methodTimes; + this.executedTests = executedTests; this.applicableIrRules = applicableIrRules; this.vmInfo = vmInfo; } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/MethodTimes.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/MethodTimes.java index 1b4cad522702..88641256b35f 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/MethodTimes.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/MethodTimes.java @@ -54,9 +54,11 @@ public void print() { int maxDurationsWidth = maxDurationsWidth(); List> sortedMethodTimes = sortByDurationAsc(); + // printf() has no '*' as dynamic-width specifier, so the calculated widths are inserted into the format string. + String format = "- %-" + (maxWidthNames + 3) + "s %" + maxDurationsWidth + "d ms%n"; + for (Map.Entry entry : sortedMethodTimes) { - System.out.printf("- %-" + (maxWidthNames + 3) + "s %" + maxDurationsWidth + "d ns%n", - entry.getKey() + ":", entry.getValue()); + System.out.printf(format, entry.getKey() + ":", entry.getValue()); } System.out.println(); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/StdoutMessages.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/StdoutMessages.java index 11b23ad42370..9118108260d3 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/StdoutMessages.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/network/testvm/java/StdoutMessages.java @@ -50,5 +50,6 @@ public void print() { for (String message : messages) { System.out.println("- " + message); } + System.out.println(); } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentsProvider.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentsProvider.java index f868fa2b82fb..c5faeed4040b 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentsProvider.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentsProvider.java @@ -27,7 +27,7 @@ * This interface provides arguments (and can set fields) for a test method. Different implementations are chosen * based on the @Arguments annotation for the @Test method. */ -interface ArgumentsProvider { +public interface ArgumentsProvider { /** * Compute arguments (and possibly set fields) for a test method. * diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java index 8b693ddcf177..0e5c4f799871 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public BaseTest(DeclaredTest test, boolean skip) { @Override public String toString() { - return "Base Test: @Test " + testMethod.getName(); + return "@Test: " + testMethod.getName(); } @Override diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java index 8959dbac2eea..287960d5703c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public CheckedTest(DeclaredTest test, Method checkMethod, Check checkSpecificati @Override public String toString() { - return "Checked Test: @Check " + checkMethod.getName() + " - @Test: " + testMethod.getName(); + return "@Test: " + testMethod.getName() + " -> @Check: " + checkMethod.getName(); } @Override diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java index bd88d44ce44b..98a829fcc015 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,9 +61,9 @@ public CustomRunTest(Method runMethod, Warmup warmUpAnno, Run runSpecification, @Override public String toString() { - String s = "Custom Run Test: @Run: " + runMethod.getName() + " - @Test"; + String s = "@Run: " + runMethod.getName() + " -> @Test"; if (tests.size() == 1) { - s += ": " + tests.get(0).getTestMethod().getName(); + s += ": " + tests.getFirst().getTestMethod().getName(); } else { s += "s: {" + tests.stream().map(t -> t.getTestMethod().getName()) .collect(Collectors.joining(",")) + "}"; @@ -105,7 +105,7 @@ protected void compileTest() { } private void compileSingleTest() { - DeclaredTest test = tests.get(0); + DeclaredTest test = tests.getFirst(); if (shouldCompile(test)) { if (isWaitForCompilation(test)) { waitForCompilation(test); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java index 15cd68bd0e3b..81143b6c2540 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,19 +34,20 @@ public class DeclaredTest { private final Method testMethod; private final ArgumentsProvider argumentsProvider; - private final int warmupIterations; private final CompLevel compLevel; + private final int warmupIterations; private final boolean allowNotCompilable; private Method attachedMethod; - public DeclaredTest(Method testMethod, ArgumentsProvider argumentsProvider, CompLevel compLevel, int warmupIterations, boolean allowNotCompilable) { + public DeclaredTest(Method testMethod, ArgumentsProvider argumentsProvider, CompLevel compLevel, int warmupIterations, + boolean allowNotCompilable) { // Make sure we can also call non-public or public methods in package private classes testMethod.setAccessible(true); this.testMethod = testMethod; - this.compLevel = compLevel; - this.allowNotCompilable = allowNotCompilable; this.argumentsProvider = argumentsProvider; + this.compLevel = compLevel; this.warmupIterations = warmupIterations; + this.allowNotCompilable = allowNotCompilable; this.attachedMethod = null; } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java index 07c1397749aa..b7c0a2201a5b 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java @@ -95,8 +95,8 @@ assertions from main() of your test! private static final boolean PRINT_TIMES = Boolean.getBoolean("PrintTimes") || VERBOSE; public static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler"); static final boolean EXCLUDE_RANDOM = Boolean.getBoolean("ExcludeRandom"); - private static final String TESTLIST = SystemProperty.getTestList(); - private static final String EXCLUDELIST = SystemProperty.getExcludeList(); + private static final String TEST_LIST = SystemProperty.getTestList(); + private static final String EXCLUDE_LIST = SystemProperty.getExcludeList(); private static final boolean DUMP_REPLAY = Boolean.getBoolean("DumpReplay"); private static final boolean GC_AFTER = Boolean.getBoolean("GCAfter"); private static final boolean SHUFFLE_TESTS = Boolean.parseBoolean(System.getProperty("ShuffleTests", "true")); @@ -122,8 +122,8 @@ assertions from main() of your test! private TestVM(Class testClass) { TestRun.check(testClass != null, "Test class cannot be null"); this.testClass = testClass; - this.testList = createTestFilterList(TESTLIST, testClass); - this.excludeList = createTestFilterList(EXCLUDELIST, testClass); + this.testList = createTestFilterList(TEST_LIST, testClass); + this.excludeList = createTestFilterList(EXCLUDE_LIST, testClass); if (PRINT_VALID_IR_RULES) { irMatchRulePrinter = new ApplicableIRRulesPrinter(); @@ -136,19 +136,20 @@ private TestVM(Class testClass) { * Parse "test1,test2,test3" into a list. */ private static List createTestFilterList(String list, Class testClass) { - List filterList = null; - if (!list.isEmpty()) { - String classPrefix = testClass.getSimpleName() + "."; - filterList = new ArrayList<>(Arrays.asList(list.split(","))); - for (int i = filterList.size() - 1; i >= 0; i--) { - String test = filterList.get(i); - if (test.indexOf(".") > 0) { - if (test.startsWith(classPrefix)) { - test = test.substring(classPrefix.length()); - filterList.set(i, test); - } else { - filterList.remove(i); - } + if (list.isEmpty()) { + return new ArrayList<>(); + } + + String classPrefix = testClass.getSimpleName() + "."; + List filterList = new ArrayList<>(Arrays.asList(list.split(","))); + for (int i = filterList.size() - 1; i >= 0; i--) { + String test = filterList.get(i); + if (test.indexOf(".") > 0) { + if (test.startsWith(classPrefix)) { + test = test.substring(classPrefix.length()); + filterList.set(i, test); + } else { + filterList.remove(i); } } } @@ -295,7 +296,7 @@ private void addBaseTests() { try { Arguments argumentsAnno = getAnnotation(m, Arguments.class); TestFormat.check(argumentsAnno != null || m.getParameterCount() == 0, "Missing @Arguments annotation to define arguments of " + m); - BaseTest baseTest = new BaseTest(test, shouldExcludeTest(m.getName())); + BaseTest baseTest = new BaseTest(test, shouldExcludeTest(m)); allTests.add(baseTest); if (PRINT_VALID_IR_RULES) { irMatchRulePrinter.emitApplicableIRRules(m, baseTest.isSkipped()); @@ -308,17 +309,22 @@ private void addBaseTests() { } /** - * Check if user wants to exclude this test by checking the -DTest and -DExclude lists. + * A test is excluded from execution if: + * - -DTest does not list the method + * - -DExclude lists the method */ - private boolean shouldExcludeTest(String testName) { - boolean hasTestList = testList != null; - boolean hasExcludeList = excludeList != null; - if (hasTestList) { - return !testList.contains(testName) || (hasExcludeList && excludeList.contains(testName)); - } else if (hasExcludeList) { - return excludeList.contains(testName); - } - return false; + private boolean shouldExcludeTest(Method testMethod) { + String testName = testMethod.getName(); + return isNotOnTestList(testName) || + isOnExcludeList(testName); + } + + private boolean isNotOnTestList(String testName) { + return !testList.isEmpty() && !testList.contains(testName); + } + + private boolean isOnExcludeList(String testName) { + return excludeList.contains(testName); } /** @@ -541,7 +547,7 @@ private void addSetupMethod(Method m) { } /** - * Setup @Test annotated method an add them to the declaredTests map to have a convenient way of accessing them + * Setup @Test annotated method and add them to the declaredTests map to have a convenient way of accessing them * once setting up a framework test (base checked, or custom run test). */ private void setupDeclaredTests() { @@ -693,7 +699,7 @@ private void addCheckedTest(Method m, Check checkAnno, Run runAnno) { + "checked test " + m); CheckedTest.Parameter parameter = getCheckedTestParameter(m, testMethod); dontCompileAndDontInlineMethod(m); - CheckedTest checkedTest = new CheckedTest(test, m, checkAnno, parameter, shouldExcludeTest(testMethod.getName())); + CheckedTest checkedTest = new CheckedTest(test, m, checkAnno, parameter, shouldExcludeTest(testMethod)); allTests.add(checkedTest); if (PRINT_VALID_IR_RULES) { // Only need to emit IR verification information if IR verification is actually performed. @@ -752,8 +758,8 @@ private void addCustomRunTest(Method m, Run runAnno) { checkCustomRunTest(m, testName, testMethod, test, runAnno.mode()); test.setAttachedMethod(m); tests.add(test); - // Only exclude custom run test if all test methods excluded - shouldExcludeTest &= shouldExcludeTest(testMethod.getName()); + // Only exclude custom run test if all its associated test methods are excluded + shouldExcludeTest &= shouldExcludeTest(testMethod); } catch (TestFormatException e) { // Logged, continue. } @@ -864,11 +870,12 @@ private void runTests() { // Execute all tests and keep track of each exception that is thrown. These are then reported once all tests // are executing. This prevents a premature exit without running all tests. for (AbstractTest test : testList) { + String testName = test.getName(); if (VERBOSE) { - System.out.println("Run " + test.toString()); + System.out.println("Run \"" + testName + "\""); } if (testFilterPresent) { - TestVmSocket.sendWithTag(MessageTag.TEST_LIST, "Run " + test.toString()); + TestVmSocket.sendWithTag(MessageTag.TEST_LIST, test.toString()); } try { test.run(); @@ -876,18 +883,18 @@ private void runTests() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); - builder.append(test).append(":").append(System.lineSeparator()).append(sw) + builder.append("Failed test: ").append(test).append(":").append(System.lineSeparator()).append(sw) .append(System.lineSeparator()).append(System.lineSeparator()); failures++; } if (PRINT_TIMES) { long endTime = System.nanoTime(); - long duration = (endTime - startTime); + long durationMs = (endTime - startTime) / 1_000_000; if (VERBOSE) { - System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1_000_000) + " ms"); + System.out.println("Done " + testName + ": " + durationMs + " ms"); } // Will be correctly formatted later. - TestVmSocket.sendWithTag(MessageTag.PRINT_TIMES, test.getName() + "," + duration); + TestVmSocket.sendWithTag(MessageTag.PRINT_TIMES, test + "," + durationMs); } if (GC_AFTER) { System.out.println("doing GC"); @@ -904,7 +911,7 @@ private void runTests() { } private boolean testFilterPresent() { - return testList != null || excludeList != null; + return !testList.isEmpty() || !excludeList.isEmpty(); } enum TriState { diff --git a/test/hotspot/jtreg/compiler/longcountedloops/TestInnerLoopConstantFoldedExitTest.java b/test/hotspot/jtreg/compiler/longcountedloops/TestInnerLoopConstantFoldedExitTest.java new file mode 100644 index 000000000000..485728adf512 --- /dev/null +++ b/test/hotspot/jtreg/compiler/longcountedloops/TestInnerLoopConstantFoldedExitTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8375639 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:StressLongCountedLoop=1 -XX:+AlwaysIncrementalInline + * -Xbatch -XX:CompileCommand=compileonly,${test.main.class}::test ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.longcountedloops; + +public class TestInnerLoopConstantFoldedExitTest { + static int offset = 1; + static final char[] array = {'a', 'b'}; + + static void loop(String s, int off) { + for (int i = 0; i < 2; i++) { + if (array[off + i] != s.charAt(i)) { + return; + } + } + } + + static void test() { + int start = offset - 1; + loop("cd", start); + loop("ab", start); + } + + public static void main(String[] args) { + for (int i = 0; i < 50_000; i++) { + test(); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java b/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java index f8abb716e425..ee75614be735 100644 --- a/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java +++ b/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2024 Red Hat and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +50,10 @@ public static void main(String[] args) { TestFramework.runWithFlags( "-XX:+IgnoreUnrecognizedVMOptions", // StressLongCountedLoop is only available in debug builds "-XX:StressLongCountedLoop=0", // Don't convert int counted loops to long ones - "-XX:PerMethodTrapLimit=100" // allow slow-path loop limit checks + // Allow slow-path loop limit checks + "-XX:PerMethodTrapLimit=100", + "-XX:+UseLoopLimitCheckPredicate", + "-XX:+UseParsePredicates" ); } diff --git a/test/hotspot/jtreg/compiler/predicates/TestDisabledLoopPredicates.java b/test/hotspot/jtreg/compiler/predicates/TestDisabledLoopPredicates.java deleted file mode 100644 index c74e22cb68a0..000000000000 --- a/test/hotspot/jtreg/compiler/predicates/TestDisabledLoopPredicates.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package compiler.predicates; - -import compiler.lib.ir_framework.*; -import jdk.test.lib.Asserts; - -/* - * @test - * @bug 8347449 - * @summary Test that profiled loop predicates are turned off if loop predicates are turned off - * @library /test/lib / - * @run driver compiler.predicates.TestDisabledLoopPredicates - */ - -public class TestDisabledLoopPredicates { - static final int SIZE = 100; - static final int MIN = 3; - - public static void main(String[] args) { - TestFramework.runWithFlags("-XX:+UseLoopPredicate", - "-XX:+UseProfiledLoopPredicate"); - TestFramework.runWithFlags("-XX:-UseLoopPredicate"); - TestFramework.runWithFlags("-XX:-UseProfiledLoopPredicate"); - } - - @Run(test = "test") - private static void check() { - int res = test(true); - Asserts.assertEQ(res, ((SIZE - 1) * SIZE - MIN * (MIN + 1)) / 2); - } - - @DontInline - private static void blackhole(int i) { - } - - @DontInline - private static int[] getArr() { - int[] arr = new int[SIZE]; - for (int i = 0; i < SIZE; i++) { - arr[i] = i; - } - - return arr; - } - - @Test - @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", - IRNode.PROFILED_LOOP_PARSE_PREDICATE, "1" }, - applyIfAnd = { "UseLoopPredicate", "true", - "UseProfiledLoopPredicate", "true" }) - @IR(failOn = { IRNode.LOOP_PARSE_PREDICATE, - IRNode.PROFILED_LOOP_PARSE_PREDICATE }, - applyIf = { "UseLoopPredicate", "false" }) - @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1" }, - failOn = { IRNode.PROFILED_LOOP_PARSE_PREDICATE }, - applyIfAnd = { "UseLoopPredicate", "true", - "UseProfiledLoopPredicate", "false" }) - public static int test(boolean cond) { - int[] arr = getArr(); - int sum = 0; - for (int i = 0; i < arr.length; i++) { - if (cond) { - if (arr[i] > MIN) { - sum += arr[i]; - } - } - blackhole(arr[i]); - } - - return sum; - } -} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/predicates/TestDisabledParsePredicates.java b/test/hotspot/jtreg/compiler/predicates/TestDisabledParsePredicates.java new file mode 100644 index 000000000000..abd484c22b8d --- /dev/null +++ b/test/hotspot/jtreg/compiler/predicates/TestDisabledParsePredicates.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package compiler.predicates; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; + +/* + * @test + * @bug 8347449 8388858 + * @summary Test that profiled loop predicates are turned off if loop predicates are turned off + * @library /test/lib / + * @run driver ${test.main.class} + */ + +public class TestDisabledParsePredicates { + static final int SIZE = 100; + static final int MIN = 3; + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+UseLoopPredicate", + "-XX:+UseProfiledLoopPredicate"); + TestFramework.runWithFlags("-XX:-UseLoopPredicate"); + TestFramework.runWithFlags("-XX:-UseProfiledLoopPredicate"); + TestFramework.runWithFlags("-XX:-UseParsePredicates"); + TestFramework.runWithFlags("-XX:-UseLoopLimitCheckPredicate"); + TestFramework.runWithFlags("-XX:-UseAutoVectorizationPredicate"); + TestFramework.runWithFlags("-XX:-ShortRunningLongLoop"); + } + + @Run(test = "test") + private static void check() { + int res = test(true); + Asserts.assertEQ(res, ((SIZE - 1) * SIZE - MIN * (MIN + 1)) / 2); + } + + @DontInline + private static void blackhole(int i) { + } + + @DontInline + private static int[] getArr() { + int[] arr = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + arr[i] = i; + } + + return arr; + } + + @Test + @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", + IRNode.PROFILED_LOOP_PARSE_PREDICATE, "1", + IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, "1", + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "1", + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "1"}, + applyIfAnd = { "UseLoopPredicate", "true", + "UseProfiledLoopPredicate", "true", + "UseLoopLimitCheckPredicate", "true", + "UseAutoVectorizationPredicate", "true", + "ShortRunningLongLoop", "true"}) + @IR(failOn = { IRNode.LOOP_PARSE_PREDICATE, + IRNode.PROFILED_LOOP_PARSE_PREDICATE }, + counts = { IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, "1", + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "1", + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "1"}, + applyIfAnd = { "UseLoopPredicate", "false", + "UseParsePredicates", "true", + "UseLoopLimitCheckPredicate", "true", + "UseAutoVectorizationPredicate", "true", + "ShortRunningLongLoop", "true"}) + @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", + IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, "1", + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "1", + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "1"}, + failOn = { IRNode.PROFILED_LOOP_PARSE_PREDICATE }, + applyIfAnd = { "UseLoopPredicate", "true", + "UseLoopLimitCheckPredicate", "true", + "UseAutoVectorizationPredicate", "true", + "ShortRunningLongLoop", "true", + "UseProfiledLoopPredicate", "false" }) + @IR(failOn = { IRNode.LOOP_PARSE_PREDICATE, + IRNode.PROFILED_LOOP_PARSE_PREDICATE, + IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE}, + applyIf = { "UseParsePredicates", "false"}) + + @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", + IRNode.PROFILED_LOOP_PARSE_PREDICATE, "1", + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "1", + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "1"}, + failOn = { IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE }, + applyIfAnd = { "UseLoopLimitCheckPredicate", "false", + "UseParsePredicates", "true" }) + @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", + IRNode.PROFILED_LOOP_PARSE_PREDICATE, "1", + IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, "1", + IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE, "1"}, + failOn = { IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE }, + applyIfAnd = { "UseAutoVectorizationPredicate", "false", + "UseParsePredicates", "true" }) + @IR(counts = { IRNode.LOOP_PARSE_PREDICATE, "1", + IRNode.PROFILED_LOOP_PARSE_PREDICATE, "1", + IRNode.LOOP_LIMIT_CHECK_PARSE_PREDICATE, "1", + IRNode.AUTO_VECTORIZATION_CHECK_PARSE_PREDICATE, "1"}, + failOn = { IRNode.SHORT_RUNNING_LONG_LOOP_PARSE_PREDICATE }, + applyIfAnd = { "ShortRunningLongLoop", "false", + "UseParsePredicates", "true" }) + public static int test(boolean cond) { + int[] arr = getArr(); + int sum = 0; + for (int i = 0; i < arr.length; i++) { + if (cond) { + if (arr[i] > MIN) { + sum += arr[i]; + } + } + blackhole(arr[i]); + } + + return sum; + } +} diff --git a/test/hotspot/jtreg/compiler/profiling/TestMethodDataObjectMutexLeak.java b/test/hotspot/jtreg/compiler/profiling/TestMethodDataObjectMutexLeak.java new file mode 100644 index 000000000000..8fe29f6822bf --- /dev/null +++ b/test/hotspot/jtreg/compiler/profiling/TestMethodDataObjectMutexLeak.java @@ -0,0 +1,187 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8390874 + * @summary Test that method unloading doesn't cause leaks of C heap allocated Mutexes in MethodData instances. + * + * @run main/othervm/timeout=600 -Xbatch + -XX:NativeMemoryTracking=summary -XX:+UnlockDiagnosticVMOptions -XX:MallocLimit=synchronization:8m -XX:-CreateCoredumpOnCrash + compiler.profiling.TestMethodDataObjectMutexLeak + */ + +package compiler.profiling; + +import java.io.IOException; +import java.io.InputStream; + +public class TestMethodDataObjectMutexLeak { + static final String CLASS_NAME = Burn.class.getName(); + static final byte[] BYTES; + + static { + try (InputStream in = TestMethodDataObjectMutexLeak.class.getResourceAsStream("/" + CLASS_NAME.replace('.', '/') + ".class")) { + BYTES = in.readAllBytes(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public static class Burn implements Runnable { + int x; + public void run() { + for (int i = 0; i < 300; i++) { + work01(i); + } + } + + public void work01(int i) { work02(i); } + public void work02(int i) { work03(i); } + public void work03(int i) { work04(i); } + public void work04(int i) { work05(i); } + public void work05(int i) { work06(i); } + public void work06(int i) { work07(i); } + public void work07(int i) { work08(i); } + public void work08(int i) { work09(i); } + public void work09(int i) { work10(i); } + public void work10(int i) { work11(i); } + public void work11(int i) { work12(i); } + public void work12(int i) { work13(i); } + public void work13(int i) { work14(i); } + public void work14(int i) { work15(i); } + public void work15(int i) { work16(i); } + public void work16(int i) { work17(i); } + public void work17(int i) { work18(i); } + public void work18(int i) { work19(i); } + public void work19(int i) { work20(i); } + public void work20(int i) { work21(i); } + public void work21(int i) { work22(i); } + public void work22(int i) { work23(i); } + public void work23(int i) { work24(i); } + public void work24(int i) { work25(i); } + public void work25(int i) { work26(i); } + public void work26(int i) { work27(i); } + public void work27(int i) { work28(i); } + public void work28(int i) { work29(i); } + public void work29(int i) { work30(i); } + public void work30(int i) { work31(i); } + public void work31(int i) { work32(i); } + public void work32(int i) { work33(i); } + public void work33(int i) { work34(i); } + public void work34(int i) { work35(i); } + public void work35(int i) { work36(i); } + public void work36(int i) { work37(i); } + public void work37(int i) { work38(i); } + public void work38(int i) { work39(i); } + public void work39(int i) { work40(i); } + public void work40(int i) { work41(i); } + public void work41(int i) { work42(i); } + public void work42(int i) { work43(i); } + public void work43(int i) { work44(i); } + public void work44(int i) { work45(i); } + public void work45(int i) { work46(i); } + public void work46(int i) { work47(i); } + public void work47(int i) { work48(i); } + public void work48(int i) { work49(i); } + public void work49(int i) { work50(i); } + public void work50(int i) { work51(i); } + public void work51(int i) { work52(i); } + public void work52(int i) { work53(i); } + public void work53(int i) { work54(i); } + public void work54(int i) { work55(i); } + public void work55(int i) { work56(i); } + public void work56(int i) { work57(i); } + public void work57(int i) { work58(i); } + public void work58(int i) { work59(i); } + public void work59(int i) { work60(i); } + public void work60(int i) { work61(i); } + public void work61(int i) { work62(i); } + public void work62(int i) { work63(i); } + public void work63(int i) { work64(i); } + public void work64(int i) { work65(i); } + public void work65(int i) { work66(i); } + public void work66(int i) { work67(i); } + public void work67(int i) { work68(i); } + public void work68(int i) { work69(i); } + public void work69(int i) { work70(i); } + public void work70(int i) { work71(i); } + public void work71(int i) { work72(i); } + public void work72(int i) { work73(i); } + public void work73(int i) { work74(i); } + public void work74(int i) { work75(i); } + public void work75(int i) { work76(i); } + public void work76(int i) { work77(i); } + public void work77(int i) { work78(i); } + public void work78(int i) { work79(i); } + public void work79(int i) { work80(i); } + public void work80(int i) { work81(i); } + public void work81(int i) { work82(i); } + public void work82(int i) { work83(i); } + public void work83(int i) { work84(i); } + public void work84(int i) { work85(i); } + public void work85(int i) { work86(i); } + public void work86(int i) { work87(i); } + public void work87(int i) { work88(i); } + public void work88(int i) { work89(i); } + public void work89(int i) { work90(i); } + public void work90(int i) { work91(i); } + public void work91(int i) { work92(i); } + public void work92(int i) { work93(i); } + public void work93(int i) { work94(i); } + public void work94(int i) { work95(i); } + public void work95(int i) { work96(i); } + public void work96(int i) { work97(i); } + public void work97(int i) { work98(i); } + public void work98(int i) { work99(i); } + public void work99(int i) { + x += i * x + 42; + } + } + + static class MyCL extends ClassLoader { + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.equals(CLASS_NAME)) { + Class c = defineClass(name, BYTES, 0, BYTES.length); + if (resolve) { + resolveClass(c); + } + return c; + } + return super.loadClass(name, resolve); + } + } + + public static void main(String[] args) throws Exception { + for (int t = 0; t < 30; t++) { + System.gc(); + System.out.println("Epoch " + t); + for (int i = 0; i < 100; i++) { + Class c = Class.forName(CLASS_NAME, true, new MyCL()); + Runnable r = (Runnable) c.getDeclaredConstructor().newInstance(); + r.run(); + } + } + System.out.println("Done."); + } +} diff --git a/test/hotspot/jtreg/compiler/regalloc/TestExceptionBranchWithLiveRangeHole.java b/test/hotspot/jtreg/compiler/regalloc/TestExceptionBranchWithLiveRangeHole.java new file mode 100644 index 000000000000..1b4d5870c411 --- /dev/null +++ b/test/hotspot/jtreg/compiler/regalloc/TestExceptionBranchWithLiveRangeHole.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.regalloc; + +/** + * @test + * @bug 8338094 + * @summary Test C1's computation of local live ranges across exception jumps. + * @run main/othervm -Xbatch + * -XX:TieredStopAtLevel=1 + * -XX:CompileCommand=compileonly,${test.main.class}::test* + * ${test.main.class} + * @run main ${test.main.class} + */ + +class TestExceptionBranchWithLiveRangeHole { + + // Test that liveness information is computed correctly by C1 for intervals + // that are live at an exception throwing operation solely because they are + // used within the exception handler block. + static void testThrowIOBE() { + int i = 0; + int[] array = new int[1]; + try { + for (;;) { + i = i << 32; + // The pre-shift value of i should be live here, because it is + // used below in the exception handler code, after the + // canonicalization (i << 32) >>> 32 => i is applied. + array[1] = 0; + } + } catch (ArrayIndexOutOfBoundsException e) { + array[i >>> 32] = 42; + } + } + + // Variant of the above test using a different type of exception. + // Illustrates the need of extending the live range of i beyond the + // o.toString() call to model the interference of i with the killed + // caller-saved registers. + static void testThrowNPE(Object o) { + int i = 0; + int[] array = new int[1]; + try { + for (;;) { + i = i << 32; + o.toString(); + } + } catch (NullPointerException e) { + array[i >>> 32] = 42; + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++) { + testThrowIOBE(); + } + for (int i = 0; i < 10_000; i++) { + testThrowNPE(null); + } + } +} diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestACmpWithNullCheckTrap.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestACmpWithNullCheckTrap.java new file mode 100644 index 000000000000..0fece27f90ee --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestACmpWithNullCheckTrap.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8390337 + * @summary Test C2 compilation of an inlined profiled acmp with a null operand + * @enablePreview + * @library /test/lib + * @run main ${test.main.class} + * @run main/othervm -Xbatch -XX:CompileOnly=${test.main.class}::test* ${test.main.class} + */ + +import jdk.test.lib.Asserts; + +public class TestACmpWithNullCheckTrap { + static Boolean getNull() { + return null; + } + + static boolean test1(Object object) { + return object == Boolean.TRUE; + } + + static boolean test2(Object object) { + return object == Boolean.TRUE; + } + + static boolean testConstantNull1() { + return test1(getNull()); + } + + static boolean testConstantNull2() { + return test2(getNull()); + } + + public static void main(String[] args) { + Object obj1 = new Object(); + Object obj2 = "42"; + + // Profile the acmp with identity classes so the operand is known not to be a value object + for (int i = 0; i < 12_000; i++) { + Asserts.assertFalse(test1(obj1)); + Asserts.assertFalse(test1(obj2)); + Asserts.assertFalse(test2(obj1)); + } + + // Compile test with its profiled operand replaced by a constant null value + for (int i = 0; i < 12_000; i++) { + Asserts.assertFalse(testConstantNull1()); + Asserts.assertFalse(testConstantNull2()); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayCheckExpansion.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayCheckExpansion.java new file mode 100644 index 000000000000..e3afb9138f59 --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayCheckExpansion.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.valhalla.inlinetypes; + +import jdk.internal.value.ValueClass; +import jdk.test.lib.Asserts; + +/** + * @test + * @bug 8391280 + * @summary Test macro expansion of merged flat-array checks with array and klass inputs + * @enablePreview + * @library /test/lib + * @modules java.base/jdk.internal.value + * @run main ${test.main.class} + * @run main/othervm -Xbatch + * -XX:CompileCommand=compileonly,${test.main.class}::test* + * ${test.main.class} + */ +public class TestFlatArrayCheckExpansion { + + static int test1(Object[] array) { + int res = 0; + for (int i = 0; i < 4; i++) { + // FlatArrayCheckNode with a Klass* input + if (ValueClass.isFlatArray(array)) { + res += 1; + } else { + res += 2; + } + // FlatArrayCheckNode with an oop input + res += (Integer)array[i]; + } + return res; + } + + // Same as test1 but different order of checks + static int test2(Object[] array) { + int res = 0; + for (int i = 0; i < 4; i++) { + // FlatArrayCheckNode with an oop input + res += (Integer)array[i]; + // FlatArrayCheckNode with a Klass* input + if (ValueClass.isFlatArray(array)) { + res += 1; + } else { + res += 2; + } + } + return res; + } + + // Same as test1 but with two different arrays + static int test3(Object[] array1, Object[] array2) { + int res = 0; + for (int i = 0; i < 4; i++) { + // FlatArrayCheckNode with a Klass* input + if (ValueClass.isFlatArray(array1)) { + res += 1; + } else { + res += 2; + } + // FlatArrayCheckNode with an oop input + res += (Integer)array2[i]; + } + return res; + } + + // Same as test2 but with two different arrays + static int test4(Object[] array1, Object[] array2) { + int res = 0; + for (int i = 0; i < 4; i++) { + // FlatArrayCheckNode with an oop input + res += (Integer)array2[i]; + // FlatArrayCheckNode with a Klass* input + if (ValueClass.isFlatArray(array1)) { + res += 1; + } else { + res += 2; + } + } + return res; + } + + public static void main(String[] args) { + Object[] refArray = {1, 2, 3, 4}; + Integer[] flatArray = {1, 2, 3, 4}; + boolean isFlat = ValueClass.isFlatArray(flatArray); + + for (int i = 0; i < 50_000; i++) { + Asserts.assertEQ(test1(refArray), 18); + Asserts.assertEQ(test1(flatArray), isFlat ? 14 : 18); + + Asserts.assertEQ(test2(refArray), 18); + Asserts.assertEQ(test2(flatArray), isFlat ? 14 : 18); + + Asserts.assertEQ(test3(refArray, refArray), 18); + Asserts.assertEQ(test3(refArray, flatArray), 18); + Asserts.assertEQ(test3(flatArray, refArray), isFlat ? 14 : 18); + Asserts.assertEQ(test3(flatArray, flatArray), isFlat ? 14 : 18); + + Asserts.assertEQ(test4(refArray, refArray), 18); + Asserts.assertEQ(test4(refArray, flatArray), 18); + Asserts.assertEQ(test4(flatArray, refArray), isFlat ? 14 : 18); + Asserts.assertEQ(test4(flatArray, flatArray), isFlat ? 14 : 18); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMarkWordLoadIdealization.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMarkWordLoadIdealization.java new file mode 100644 index 000000000000..e5a9e5674329 --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMarkWordLoadIdealization.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.valhalla.inlinetypes; + +import compiler.lib.ir_framework.*; +import jdk.internal.misc.Unsafe; +import jdk.internal.value.ValueClass; +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; + +/** + * @test + * @summary Test that loads of object markword bits that are know at JIT-compile + * time are constant-folded by C2 idealizations. + * @library /test/lib / + * @requires vm.compiler2.enabled & vm.flagless + * @enablePreview + * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.value + * @run driver ${test.main.class} + */ + +public class TestMarkWordLoadIdealization { + + // Wrap these variables into helper class because WhiteBox API needs to be + // initialized by TestFramework first. + static class WB { + static final long MARK_WORD_OFFSET = WhiteBox.getWhiteBox().getMarkWordOffset(); + static final long INLINE_TYPE_PATTERN = WhiteBox.getWhiteBox().getInlineTypePattern(); + static final long NULL_FREE_ARRAY_BIT_IN_PLACE = WhiteBox.getWhiteBox().getNullFreeArrayBitInPlace(); + static final long FLAT_ARRAY_BIT_IN_PLACE = WhiteBox.getWhiteBox().getFlatArrayBitInPlace(); + } + + static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + static final Object IDENTITY_OBJECT = new Object(); + static final Integer VALUE_OBJECT = Integer.valueOf(42); + + static final String[] IDENTITY_OBJECT_ARRAY = new String[1]; + static final Integer[] VALUE_OBJECT_ARRAY = new Integer[1]; + static final Integer[] VALUE_OBJECT_ARRAY_NULL_RESTRICTED = + (Integer[]) ValueClass.newNullRestrictedNonAtomicArray(Integer.class, 2, Integer.valueOf(0)); + + public static void main(String[] args) { + TestFramework.runWithFlags("--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", + "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", + "--enable-preview"); + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testInlineTypePatternBitLoadNegativeIdealization() { + return (UNSAFE.getLong(IDENTITY_OBJECT, WB.MARK_WORD_OFFSET) & WB.INLINE_TYPE_PATTERN) != 0L; + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testInlineTypePatternBitLoadPositiveIdealization() { + return (UNSAFE.getLong(VALUE_OBJECT, WB.MARK_WORD_OFFSET) & WB.INLINE_TYPE_PATTERN) != 0L; + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testNullFreeArrayBitLoadNegativeIdealization() { + return (UNSAFE.getLong(VALUE_OBJECT_ARRAY, WB.MARK_WORD_OFFSET) & WB.NULL_FREE_ARRAY_BIT_IN_PLACE) != 0L; + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testNullFreeArrayBitLoadPositiveIdealization() { + return (UNSAFE.getLong(VALUE_OBJECT_ARRAY_NULL_RESTRICTED, WB.MARK_WORD_OFFSET) & WB.NULL_FREE_ARRAY_BIT_IN_PLACE) != 0L; + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testFlatArrayBitLoadNegativeIdealization() { + return (UNSAFE.getLong(IDENTITY_OBJECT_ARRAY, WB.MARK_WORD_OFFSET) & WB.FLAT_ARRAY_BIT_IN_PLACE) != 0L; + } + + @Test + @IR(failOn = IRNode.LOAD_L) + public static boolean testFlatArrayBitLoadPositiveIdealization() { + return (UNSAFE.getLong(VALUE_OBJECT_ARRAY, WB.MARK_WORD_OFFSET) & WB.FLAT_ARRAY_BIT_IN_PLACE) != 0L; + } + + @Run(test = {"testInlineTypePatternBitLoadNegativeIdealization", + "testInlineTypePatternBitLoadPositiveIdealization", + "testNullFreeArrayBitLoadNegativeIdealization", + "testNullFreeArrayBitLoadPositiveIdealization", + "testFlatArrayBitLoadNegativeIdealization", + "testFlatArrayBitLoadPositiveIdealization"}) + void run() { + Asserts.assertFalse(testInlineTypePatternBitLoadNegativeIdealization()); + Asserts.assertTrue(testInlineTypePatternBitLoadPositiveIdealization()); + Asserts.assertFalse(testNullFreeArrayBitLoadNegativeIdealization()); + Asserts.assertTrue(testNullFreeArrayBitLoadPositiveIdealization()); + Asserts.assertFalse(testFlatArrayBitLoadNegativeIdealization()); + Asserts.assertTrue(testFlatArrayBitLoadPositiveIdealization()); + } +} diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java index 0a641ba2961a..a4a68b5f9ea3 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java @@ -3018,7 +3018,6 @@ public static Object hide(Object obj) { } // Test that the ConstraintCastNode::Ideal transformation propagates null-free information - /* TODO 8389088: Re-enable once fixed. @Test public MyValue1 test103() { Object obj = hide(null); @@ -3029,7 +3028,6 @@ public MyValue1 test103() { public void test103_verifier() { Asserts.assertEQ(test103(), null); } - */ // Test null restricted fields diff --git a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java index b95771d98629..a88c7d5c36ef 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java @@ -240,6 +240,160 @@ public static void testMaskAndNotL() { } } + @Test + @IR(counts = { IRNode.RISCV_VMASK_NOT_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNotI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + avm.not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(!ma[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_NOT_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNotL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + avm.not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(!ma[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_NAND_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNandI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.and(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] & mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_NAND_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNandL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.and(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] & mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_NOR_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNorI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.or(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] | mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_NOR_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskNorL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.or(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] | mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_XNOR_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskXnorI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.xor(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] ^ mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_XNOR_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskXnorL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.xor(bvm).not().intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(!(ma[i] ^ mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_XNOR_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskEqI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.eq(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(ma[i] == mb[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_XNOR_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskEqL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.eq(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(ma[i] == mb[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_OR_NOT_I, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskOrNotI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.or(bvm.not()).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(ma[i] | !mb[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.RISCV_VMASK_OR_NOT_L, "1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testMaskOrNotL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.or(bvm.not()).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(ma[i] | !mb[i], mr[i]); + } + } + // Tests that mask.not().and(other) matches to VMASK_AND_NOT (AndVMask commutative rule). @Test @IR(counts = { IRNode.VMASK_AND_NOT_I, "1" }, applyIfCPUFeatureOr = {"sve", "true", "rvv", "true"}) diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorBroadcastTransforms.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorBroadcastTransforms.java index c58a6710c868..b09d71700509 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorBroadcastTransforms.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorBroadcastTransforms.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8358521 + * @bug 8358521 8389666 * @summary Optimize vector operations by reassociating broadcasted inputs * @modules jdk.incubator.vector * @library /test/lib / @@ -55,7 +55,7 @@ public static void main(String[] args) { @Test @IR(failOn = IRNode.ADD_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_add(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -73,7 +73,7 @@ static void run_int_add() { @Test @IR(failOn = IRNode.SUB_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_sub(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -91,7 +91,7 @@ static void run_int_sub() { @Test @IR(failOn = IRNode.MUL_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_mul(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -107,9 +107,44 @@ static void run_int_mul() { Verify.checkEQ(ir, ia * ib); } + // Integer vector DIV is currently matched on SVE and RVV. push_through_replicate + // must be able to scalarize DivVI via VectorNode::make_scalar(Op_DivI). + @Test + @IR(failOn = IRNode.DIV_VI, + applyIfCPUFeatureOr = {"sve", "true", "rvv", "true"}, + counts = { IRNode.DIV_I, ">= 1", + IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) + static int int_div(int ia, int ib) { + return IntVector.broadcast(ISP, ia) + .lanewise(VectorOperators.DIV, IntVector.broadcast(ISP, ib)) + .lane(0); + } + + @Run(test = "int_div") + static void run_int_div() { + int ia = R.nextInt(); + int ib = R.nextInt(); + if (ib == 0) ib = 1; + int ir = int_div(ia, ib); + Verify.checkEQ(ir, ia / ib); + } + + // Minimal crash reproducer from VectorExpressionFuzzer (constant broadcasts). + @Test + static int int_div_broadcast_constants() { + return IntVector.broadcast(IntVector.SPECIES_128, -4096) + .div(IntVector.broadcast(IntVector.SPECIES_128, 1)) + .lane(0); + } + + @Run(test = "int_div_broadcast_constants") + static void run_int_div_broadcast_constants() { + Verify.checkEQ(int_div_broadcast_constants(), -4096); + } + @Test @IR(failOn = IRNode.AND_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.AND_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_and(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -127,7 +162,7 @@ static void run_int_and() { @Test @IR(failOn = IRNode.OR_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.OR_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_or(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -145,7 +180,7 @@ static void run_int_or() { @Test @IR(failOn = IRNode.XOR_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.XOR_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_xor(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -163,7 +198,7 @@ static void run_int_xor() { @Test @IR(failOn = IRNode.MIN_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MIN_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_min(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -181,7 +216,7 @@ static void run_int_min() { @Test @IR(failOn = IRNode.MAX_VI, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MAX_I, ">= 1", IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static int int_max(int ia, int ib) { return IntVector.broadcast(ISP, ia) @@ -205,7 +240,7 @@ static void run_int_max() { @Test @IR(failOn = IRNode.ADD_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_add(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -223,7 +258,7 @@ static void run_long_add() { @Test @IR(failOn = IRNode.SUB_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_sub(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -241,7 +276,7 @@ static void run_long_sub() { @Test @IR(failOn = IRNode.MUL_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_mul(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -257,9 +292,29 @@ static void run_long_mul() { Verify.checkEQ(lr, la * lb); } + @Test + @IR(failOn = IRNode.DIV_VL, + applyIfCPUFeatureOr = {"sve", "true", "rvv", "true"}, + counts = { IRNode.DIV_L, ">= 1", + IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) + static long long_div(long la, long lb) { + return LongVector.broadcast(LSP, la) + .div(LongVector.broadcast(LSP, lb)) + .lane(0); + } + + @Run(test = "long_div") + static void run_long_div() { + long la = R.nextLong(); + long lb = R.nextLong(); + if (lb == 0L) lb = 1L; + long lr = long_div(la, lb); + Verify.checkEQ(lr, la / lb); + } + @Test @IR(failOn = IRNode.AND_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.AND_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_and(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -277,7 +332,7 @@ static void run_long_and() { @Test @IR(failOn = IRNode.OR_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.OR_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_or(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -295,7 +350,7 @@ static void run_long_or() { @Test @IR(failOn = IRNode.XOR_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.XOR_L, ">= 1", IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_xor(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -313,7 +368,7 @@ static void run_long_xor() { @Test @IR(failOn = IRNode.MIN_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = {IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_min(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -331,7 +386,7 @@ static void run_long_min() { @Test @IR(failOn = IRNode.MAX_VL, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = {IRNode.REPLICATE_L, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static long long_max(long la, long lb) { return LongVector.broadcast(LSP, la) @@ -355,7 +410,7 @@ static void run_long_max() { @Test @IR(failOn = IRNode.ADD_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_add(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -373,7 +428,7 @@ static void run_float_add() { @Test @IR(failOn = IRNode.SUB_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_sub(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -391,7 +446,7 @@ static void run_float_sub() { @Test @IR(failOn = IRNode.MUL_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_mul(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -409,7 +464,7 @@ static void run_float_mul() { @Test @IR(failOn = IRNode.DIV_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.DIV_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_div(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -428,7 +483,7 @@ static void run_float_div() { @Test @IR(failOn = IRNode.MIN_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MIN_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_min(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -446,7 +501,7 @@ static void run_float_min() { @Test @IR(failOn = IRNode.MAX_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MAX_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_max(float fa, float fb) { return FloatVector.broadcast(FSP, fa) @@ -464,7 +519,7 @@ static void run_float_max() { @Test @IR(failOn = IRNode.SQRT_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SQRT_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_sqrt(float fa) { return FloatVector.broadcast(FSP, fa) @@ -481,7 +536,7 @@ static void run_float_sqrt() { @Test @IR(failOn = IRNode.FMA_VF, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.FMA_F, ">= 1", IRNode.REPLICATE_F, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static float float_fma(float fa, float fb, float fc) { return FloatVector.broadcast(FSP, fa) @@ -507,7 +562,7 @@ static void run_float_fma() { @Test @IR(failOn = IRNode.ADD_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_add(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -525,7 +580,7 @@ static void run_double_add() { @Test @IR(failOn = IRNode.SUB_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_sub(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -543,7 +598,7 @@ static void run_double_sub() { @Test @IR(failOn = IRNode.MUL_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_mul(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -561,7 +616,7 @@ static void run_double_mul() { @Test @IR(failOn = IRNode.DIV_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.DIV_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_div(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -580,7 +635,7 @@ static void run_double_div() { @Test @IR(failOn = IRNode.MIN_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MIN_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_min(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -598,7 +653,7 @@ static void run_double_min() { @Test @IR(failOn = IRNode.MAX_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MAX_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_max(double da, double db) { return DoubleVector.broadcast(DSP, da) @@ -616,7 +671,7 @@ static void run_double_max() { @Test @IR(failOn = IRNode.SQRT_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SQRT_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_sqrt(double da) { return DoubleVector.broadcast(DSP, da) @@ -633,7 +688,7 @@ static void run_double_sqrt() { @Test @IR(failOn = IRNode.FMA_VD, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.FMA_D, ">= 1", IRNode.REPLICATE_D, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static double double_fma(double da, double db, double dc) { return DoubleVector.broadcast(DSP, da) @@ -661,7 +716,7 @@ static void run_double_fma() { @Test @IR(failOn = IRNode.ADD_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_add(byte ba, byte bb) { @@ -680,7 +735,7 @@ static void run_byte_add() { @Test @IR(failOn = IRNode.SUB_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_sub(byte ba, byte bb) { @@ -699,7 +754,7 @@ static void run_byte_sub() { @Test @IR(failOn = IRNode.ADD_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_add_overflow() { @@ -716,7 +771,7 @@ static void run_byte_add_overflow() { @Test @IR(failOn = IRNode.ADD_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_add_underflow() { @@ -733,7 +788,7 @@ static void run_byte_add_underflow() { @Test @IR(failOn = IRNode.SUB_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_sub_overflow() { @@ -750,7 +805,7 @@ static void run_byte_sub_overflow() { @Test @IR(failOn = IRNode.SUB_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_sub_underflow() { @@ -767,7 +822,7 @@ static void run_byte_sub_underflow() { @Test @IR(failOn = IRNode.MUL_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_mul(byte ba, byte bb) { @@ -784,9 +839,29 @@ static void run_byte_mul() { Verify.checkEQ(br, (byte) (ba * bb)); } + @Test + @IR(failOn = IRNode.DIV_VB, + applyIfCPUFeatureOr = {"sve", "true", "rvv", "true"}, + counts = { IRNode.DIV_I, ">= 1", + IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) + static byte byte_div(byte ba, byte bb) { + return ByteVector.broadcast(BSP, ba) + .div(ByteVector.broadcast(BSP, bb)) + .lane(0); + } + + @Run(test = "byte_div") + static void run_byte_div() { + byte ba = (byte) R.nextInt(); + byte bb = (byte) R.nextInt(); + if (bb == 0) bb = 1; + byte br = byte_div(ba, bb); + Verify.checkEQ(br, (byte) (ba / bb)); + } + @Test @IR(failOn = IRNode.AND_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.AND_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_and(byte ba, byte bb) { return ByteVector.broadcast(BSP, ba) @@ -804,7 +879,7 @@ static void run_byte_and() { @Test @IR(failOn = IRNode.OR_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.OR_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_or(byte ba, byte bb) { return ByteVector.broadcast(BSP, ba) @@ -822,7 +897,7 @@ static void run_byte_or() { @Test @IR(failOn = IRNode.XOR_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.XOR_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_xor(byte ba, byte bb) { return ByteVector.broadcast(BSP, ba) @@ -840,7 +915,7 @@ static void run_byte_xor() { @Test @IR(failOn = IRNode.MIN_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MIN_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_min(byte ba, byte bb) { return ByteVector.broadcast(BSP, ba) @@ -858,7 +933,7 @@ static void run_byte_min() { @Test @IR(failOn = IRNode.MAX_VB, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MAX_I, ">= 1", IRNode.REPLICATE_B, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static byte byte_max(byte ba, byte bb) { return ByteVector.broadcast(BSP, ba) @@ -884,7 +959,7 @@ static void run_byte_max() { @Test @IR(failOn = IRNode.ADD_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_add(short sa, short sb) { @@ -903,7 +978,7 @@ static void run_short_add() { @Test @IR(failOn = IRNode.SUB_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_sub(short sa, short sb) { @@ -922,7 +997,7 @@ static void run_short_sub() { @Test @IR(failOn = IRNode.ADD_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_add_overflow() { @@ -939,7 +1014,7 @@ static void run_short_add_overflow() { @Test @IR(failOn = IRNode.ADD_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.ADD_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_add_underflow() { @@ -956,7 +1031,7 @@ static void run_short_add_underflow() { @Test @IR(failOn = IRNode.SUB_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_sub_overflow() { @@ -973,7 +1048,7 @@ static void run_short_sub_overflow() { @Test @IR(failOn = IRNode.SUB_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.SUB_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_sub_underflow() { @@ -990,7 +1065,7 @@ static void run_short_sub_underflow() { @Test @IR(failOn = IRNode.MUL_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MUL_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_mul(short sa, short sb) { @@ -1007,9 +1082,29 @@ static void run_short_mul() { Verify.checkEQ(sr, (short) (sa * sb)); } + @Test + @IR(failOn = IRNode.DIV_VS, + applyIfCPUFeatureOr = {"sve", "true", "rvv", "true"}, + counts = { IRNode.DIV_I, ">= 1", + IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) + static short short_div(short sa, short sb) { + return ShortVector.broadcast(SSP, sa) + .div(ShortVector.broadcast(SSP, sb)) + .lane(0); + } + + @Run(test = "short_div") + static void run_short_div() { + short sa = (short) R.nextInt(); + short sb = (short) R.nextInt(); + if (sb == 0) sb = 1; + short sr = short_div(sa, sb); + Verify.checkEQ(sr, (short) (sa / sb)); + } + @Test @IR(failOn = IRNode.AND_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.AND_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_and(short sa, short sb) { return ShortVector.broadcast(SSP, sa) @@ -1027,7 +1122,7 @@ static void run_short_and() { @Test @IR(failOn = IRNode.OR_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.OR_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_or(short sa, short sb) { return ShortVector.broadcast(SSP, sa) @@ -1045,7 +1140,7 @@ static void run_short_or() { @Test @IR(failOn = IRNode.XOR_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.XOR_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_xor(short sa, short sb) { return ShortVector.broadcast(SSP, sa) @@ -1063,7 +1158,7 @@ static void run_short_xor() { @Test @IR(failOn = IRNode.MIN_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MIN_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_min(short sa, short sb) { return ShortVector.broadcast(SSP, sa) @@ -1081,7 +1176,7 @@ static void run_short_min() { @Test @IR(failOn = IRNode.MAX_VS, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, counts = { IRNode.MAX_I, ">= 1", IRNode.REPLICATE_S, IRNode.VECTOR_SIZE_ANY, ">= 1" }) static short short_max(short sa, short sb) { return ShortVector.broadcast(SSP, sa) diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorLogicConeFuzzer.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLogicConeFuzzer.java new file mode 100644 index 000000000000..f600b470e9a7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLogicConeFuzzer.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8387204 + * @key randomness + * @summary Fuzzer for the C2 vector "logic cone" (MacroLogicV) packing optimization. + * @requires vm.compiler2.enabled + * @requires os.simpleArch == "x64" + * @modules jdk.incubator.vector + * @library /test/lib / + * @compile ../../compiler/lib/verify/Verify.java + * @run driver ${test.main.class} + */ + +package compiler.vectorapi; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.Random; + +import jdk.test.lib.Utils; + +import compiler.lib.compile_framework.CompileFramework; + +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.scope; +import static compiler.lib.template_framework.Template.let; + +import compiler.lib.template_framework.library.Expression; +import compiler.lib.template_framework.library.Expression.Nesting; +import compiler.lib.template_framework.library.PrimitiveType; +import compiler.lib.template_framework.library.TestFrameworkClass; +import compiler.lib.template_framework.library.VectorType; + +/** + * Fuzzer for the vector logic-cone (MacroLogicV) optimization. + * + *

The generated tests build random expression trees using only bitwise logic + * operations, fed by exactly three input vectors, so that C2's + * {@code Compile::optimize_logic_cones} folds them into {@code MacroLogicV} (ternary + * truth-table) nodes. + * + *

Predication is fuzzed too: a cone freely mixes non-predicated operations with + * predicated ones, and a cone may use more than one mask ({@code m0}, {@code m1}). + * + */ +public class TestVectorLogicConeFuzzer { + private static final Random RANDOM = Utils.getRandomInstance(); + + // A non-predicated MacroLogicV is a pure bitwise fold, so it is inferred for every + // integral element type; only the vector size matters (>= 128-bit, see the AVX512VL + // requirement in Matcher::match_rule_supported_vector). Byte and short are therefore + // covered as well, and only predication is restricted (see canPredicate below). + private static final List LOGIC_TYPES = List.of( + VectorType.BYTE_128, VectorType.BYTE_256, VectorType.BYTE_512, + VectorType.SHORT_128, VectorType.SHORT_256, VectorType.SHORT_512, + VectorType.INT_128, VectorType.INT_256, VectorType.INT_512, + VectorType.LONG_128, VectorType.LONG_256, VectorType.LONG_512 + ); + + private static final int SAMPLES_PER_TYPE = 15; + + // A predicated MacroLogicV maps to masked x86 VPTERNLOGD/Q, which is only defined for 32- + // and 64-bit lanes; Matcher::match_rule_supported_vector_masked rejects any other element + // type. Cones over byte and short are therefore generated non-predicated only. + private static boolean canPredicate(VectorType.Vector t) { + String carrier = t.elementType.carrierTypeName(); + return carrier.equals("int") || carrier.equals("long"); + } + + // Maximum number of distinct masks a single cone may use. A cone using one mask can pack + // entirely into a predicated MacroLogicV; a cone using two masks forces the packing logic + // to keep the differently-predicated parts apart. + private static final int MAX_MASKS = 2; + + // Logic-only operation pool for a given vector type: the non-predicated operations plus, + // for each of the "numMasks" masks m0..m declared in the generated method, the + // predicated counterparts. Cones are nested from this pool at random, so they mix + // non-predicated ops, ops sharing a mask, and ops under different masks. + // + // The operation set is exactly AndV, OrV, XorV and Not. Not is a unary op that C2 lowers to + // a XorV with an all-ones vector; both encodings are generated: + // - all-ones in in(2): v.not() / v.lanewise(NOT, m) + // - all-ones in in(1): allOnes.lanewise(XOR, v [, m]) + private static List logicOps(VectorType.Vector t, int numMasks) { + String allOnes = t.name() + ".broadcast(" + t.speciesName + ", -1)"; + List ops = new ArrayList<>(List.of( + Expression.make(t, "", t, ".lanewise(VectorOperators.AND, ", t, ")"), // AndV + Expression.make(t, "", t, ".lanewise(VectorOperators.OR, ", t, ")"), // OrV + Expression.make(t, "", t, ".lanewise(VectorOperators.XOR, ", t, ")"), // XorV + Expression.make(t, "", t, ".not()"), // Not, all-ones in in(2) + Expression.make(t, allOnes + ".lanewise(VectorOperators.XOR, ", t, ")") // Not, all-ones in in(1) + )); + for (int i = 0; i < numMasks; i++) { + String m = ", m" + i + ")"; + ops.add(Expression.make(t, "", t, ".lanewise(VectorOperators.AND, ", t, m)); // AndV + ops.add(Expression.make(t, "", t, ".lanewise(VectorOperators.OR, ", t, m)); // OrV + ops.add(Expression.make(t, "", t, ".lanewise(VectorOperators.XOR, ", t, m)); // XorV + ops.add(Expression.make(t, "", t, ".lanewise(VectorOperators.NOT, m" + i + ")")); // Not, all-ones in in(2) + ops.add(Expression.make(t, allOnes + ".lanewise(VectorOperators.XOR, ", t, m)); // Not, all-ones in in(1) + } + return ops; + } + + public static void main(String[] args) { + CompileFramework comp = new CompileFramework(); + comp.addJavaSourceCode("compiler.vectorapi.templated.LogicConeTemplated", generate(comp)); + comp.compile("--add-modules=jdk.incubator.vector"); + + List vmArgs = new ArrayList<>(List.of( + "--add-modules=jdk.incubator.vector" + )); + vmArgs.addAll(Arrays.asList(args)); + + comp.invoke("compiler.vectorapi.templated.LogicConeTemplated", "main", + new Object[] { vmArgs.toArray(new String[0]) }); + } + + public static String generate(CompileFramework comp) { + List tests = new ArrayList<>(); + + // Emit the LibraryRNG helper class used to fill the input arrays. + tests.add(PrimitiveType.generateLibraryRNG()); + + // Body shared by the compiled ($test) and reference ($reference) methods. + var bodyTemplate = Template.make("expression", "arguments", "decls", + (Expression expression, List arguments, List decls) -> { + VectorType.Vector retType = (VectorType.Vector) expression.returnType; + return scope( + let("carrierType", retType.elementType.carrierTypeName()), + decls, + "#carrierType[] out = new #carrierType[1000];\n", + expression.asToken(arguments), ".intoArray(out, 0);\n", + "return out;\n" + ); + }); + + var testTemplate = Template.make("type", (VectorType.Vector type) -> { + int numMasks = canPredicate(type) ? RANDOM.nextInt(1, MAX_MASKS + 1) : 0; + + // Generate a cone with at least 3 leaves so it can be fed by exactly 3 inputs. + Expression expression; + int attempts = 0; + do { + int depth = RANDOM.nextInt(3, 8); // roughly the number of logic ops in the cone + expression = Expression.nestRandomly(type, logicOps(type, numMasks), depth, Nesting.EXACT); + } while (expression.argumentTypes.size() < 3 && ++attempts < 50); + + String carrier = type.elementType.carrierTypeName(); + + // MacroLogicV is a ternary (3-input) truth-table node, so it is only inferred + // when the whole cone is fed by exactly 3 distinct input vectors. Feed the leaves + // from v0, v1, v2 round-robin: this uses each input at least once and keeps the + // two operands of every binary op distinct, avoiding self-cancelling identities + // (e.g. v ^ v == 0) that would collapse the cone away from a MacroLogicV. + List useArgs = new ArrayList<>(); + for (int i = 0; i < expression.argumentTypes.size(); i++) { + var at = expression.argumentTypes.get(i); + if (!(at instanceof VectorType.Vector)) { + throw new RuntimeException("unexpected argument type in logic cone: " + at); + } + useArgs.add("v" + (i % 3)); + } + + // Declarations shared by the compiled and the reference method: each mask once, + // then v0..v2 loaded once from the three input arrays. + List decls = new ArrayList<>(); + for (int i = 0; i < numMasks; i++) { + decls.add(List.of("var m", Integer.toString(i), " = VectorMask.fromArray(", + type.speciesName, ", mask_arr_", Integer.toString(i), ", 0);\n")); + } + for (int j = 0; j < 3; j++) { + decls.add(List.of("var v", Integer.toString(j), " = ", type.name(), + ".fromArray(", type.speciesName, ", arg_", Integer.toString(j), ", 0);\n")); + } + + // Method arguments: the 3 input arrays followed by one array per mask. + List defineAndFill = new ArrayList<>(); + StringBuilder passArgs = new StringBuilder("arg_0, arg_1, arg_2"); + List receiveArgs = new ArrayList<>(); + receiveArgs.add(List.of(carrier, "[] arg_0, ", carrier, "[] arg_1, ", carrier, "[] arg_2")); + for (int j = 0; j < 3; j++) { + String a = "arg_" + j; + defineAndFill.add(List.of(carrier, "[] ", a, " = new ", carrier, "[1000];\n", + "LibraryRNG.fill(", a, ");\n")); + } + for (int i = 0; i < numMasks; i++) { + String ma = "mask_arr_" + i; + defineAndFill.add("boolean[] " + ma + " = new boolean[1000];\nLibraryRNG.fill(" + ma + ");\n"); + passArgs.append(", ").append(ma); + receiveArgs.add(", boolean[] " + ma); + } + + // MacroLogicV IR matching is only asserted for non-masked cones; masked + // cones may not pack into MacroLogicV (e.g. mixed masks or partial predication). + Object testMethodHeader = numMasks == 0 + ? """ + @IR(applyIf = {"UseAVX", "3"}, counts = {IRNode.MACRO_LOGIC_V, " > 0 "}) + @Test + public static Object $test( + """ + : """ + @Test + public static Object $test( + """; + + return scope( + let("leaves", expression.argumentTypes.size()), + let("masks", numMasks), + """ + // --- $test start (type: #type, leaves: #leaves, inputs: 3, masks: #masks) --- + @Run(test = "$test") + public void $run() { + """, + defineAndFill, + " Object r0 = $test(" + passArgs + ");\n", + " Object r1 = $reference(" + passArgs + ");\n", + " Verify.checkEQ(r0, r1);\n", + """ + } + + """, + testMethodHeader, + receiveArgs, + """ + ) { + """, + bodyTemplate.asToken(expression, useArgs, decls), + """ + } + + @DontCompile + public static Object $reference( + """, + receiveArgs, + """ + ) { + """, + bodyTemplate.asToken(expression, useArgs, decls), + """ + } + // --- $test end --- + """ + ); + }); + + for (VectorType.Vector type : LOGIC_TYPES) { + for (int i = 0; i < SAMPLES_PER_TYPE; i++) { + tests.add(testTemplate.asToken(type)); + } + } + + return TestFrameworkClass.render( + "compiler.vectorapi.templated", "LogicConeTemplated", + Set.of("compiler.lib.verify.*", + "compiler.lib.generators.*", + "jdk.incubator.vector.*", + "java.util.Random", + "jdk.test.lib.Utils"), + comp.getEscapedClassPathOfCompiledClasses(), + tests); + } +} diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index 4240ba408b76..065f9ed8a7be 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -75,7 +75,7 @@ private static void test() throws Exception { DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "WaitForFlagFile"); Object lock = new Object(); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); - opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp/"); + opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp/:z"); opts.addJavaOpts("-Xlog:os+container=trace", "-Xlog:perf*=debug", "-cp", "/test-classes/"); Thread t1 = new Thread() { diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index 68afe2b2db35..b6682ec37ebc 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -84,7 +84,7 @@ private static void testLimitUpdates() throws Exception { started.delete(); DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "LimitUpdateChecker"); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); - opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp"); + opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp:z"); opts.addDockerOpts("--cpu-period", Integer.toString(CPU_PERIOD)); opts.addDockerOpts("--cpu-quota", Integer.toString(INITIAL_CPU_COUNT * CPU_PERIOD)); opts.addDockerOpts("--memory", "500m"); diff --git a/test/hotspot/jtreg/gc/TestGCALotAtAllSafepoints.java b/test/hotspot/jtreg/gc/TestGCALotAtAllSafepoints.java index 76a0482322a9..fa03d7341c13 100644 --- a/test/hotspot/jtreg/gc/TestGCALotAtAllSafepoints.java +++ b/test/hotspot/jtreg/gc/TestGCALotAtAllSafepoints.java @@ -100,10 +100,15 @@ public class TestGCALotAtAllSafepoints { public static void main(String[] args) throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args[0], "-Xmx16m", + // Even this small test can generate thousands of GCs. Reduce them. + "-XX:ScavengeALotInterval=13", "-XX:+GCALotAtAllSafepoints", "-XX:+ScavengeALot", + "-Xlog:gc,gc+start,safepoint", "NoSuchClass"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + Process process = ProcessTools.startProcess("gcalot", pb); + OutputAnalyzer output = new OutputAnalyzer(process); output.shouldMatch("Error: Could not find or load main class NoSuchClass"); output.shouldHaveExitValue(1); } diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceFirstGC.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceFirstGC.java new file mode 100644 index 000000000000..1bebe7c86d8a --- /dev/null +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceFirstGC.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 TestMetaspaceFirstGC + * @bug 8208250 + * @summary Verify that the first metaspace GC happens near the MetaspaceSize threshold + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm -Xms200m TestMetaspaceFirstGC + * @run main/othervm -Xms200m -XX:MetaspaceSize=10m TestMetaspaceFirstGC 10m + * @run main/othervm -Xms200m -XX:MetaspaceSize=50m TestMetaspaceFirstGC 50m + * @run main/othervm -Xms200m -XX:MetaspaceSize=99m TestMetaspaceFirstGC 99m + */ + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URL; +import java.net.URLClassLoader; +import java.time.Duration; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +public class TestMetaspaceFirstGC { + + private static int classCounter = 0; + + public interface Dummy {} + + static class DummyHandler implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + } + + public static void main(String[] args) throws Exception { + long expectedSize = -1; + if (args.length > 0) { + expectedSize = parseSize(args[0]); + } + + try (Recording recording = new Recording()) { + recording.enable(EventNames.GarbageCollection); + recording.enable(EventNames.MetaspaceSummary).withThreshold(Duration.ofMillis(0)); + recording.start(); + + // Load classes until a metaspace-triggered GC happens + loadClassesUntilGC(50000); + + recording.stop(); + + List events = Events.fromRecordingOrdered(recording); + + // Find first GarbageCollection with cause "Metadata GC Threshold" + RecordedEvent gcEvent = null; + for (RecordedEvent event : events) { + if (event.getEventType().getName().equals(EventNames.GarbageCollection)) { + String cause = event.getString("cause"); + if ("Metadata GC Threshold".equals(cause)) { + gcEvent = event; + break; + } + } + } + + if (gcEvent == null) { + throw new RuntimeException("No GC with cause 'Metadata GC Threshold' found"); + } + + int gcId = gcEvent.getInt("gcId"); + System.out.println("Found Metadata GC Threshold GC, gcId=" + gcId); + + // Find matching MetaspaceSummary with same gcId and when="Before GC" + RecordedEvent msEvent = null; + for (RecordedEvent event : events) { + if (event.getEventType().getName().equals(EventNames.MetaspaceSummary)) { + if (event.getInt("gcId") == gcId && "Before GC".equals(event.getString("when"))) { + msEvent = event; + break; + } + } + } + + if (msEvent == null) { + throw new RuntimeException("No MetaspaceSummary 'Before GC' found for gcId=" + gcId); + } + + long committed = msEvent.getLong("metaspace.committed"); + long gcThreshold = msEvent.getLong("gcThreshold"); + System.out.println("MetaspaceSummary: committed=" + committed + " gcThreshold=" + gcThreshold); + + // committed should be reasonably close to gcThreshold + long tolerance = 5 * 1024 * 1024; // 5MB tolerance + Asserts.assertLessThanOrEqual(Math.abs(committed - gcThreshold), tolerance, + "committed (" + committed + ") should be close to gcThreshold (" + gcThreshold + ")"); + + // If explicit MetaspaceSize given, gcThreshold should match it + if (expectedSize > 0) { + Asserts.assertLessThanOrEqual(Math.abs(gcThreshold - expectedSize), tolerance, + "gcThreshold (" + gcThreshold + ") should be close to MetaspaceSize (" + expectedSize + ")"); + System.out.println("gcThreshold matches expected MetaspaceSize=" + expectedSize); + } else { + // No explicit MetaspaceSize — check default range (~12MB to ~20MB per tuning guide) + Asserts.assertGreaterThan(gcThreshold, 11_500_000L, + "default gcThreshold (" + gcThreshold + ") too small"); + Asserts.assertLessThan(gcThreshold, 22_500_000L, + "default gcThreshold (" + gcThreshold + ") too large"); + System.out.println("gcThreshold in expected default range"); + } + + System.out.println("PASSED"); + } + } + + private static void loadClassesUntilGC(int maxIterations) { + long prevUsed = getMetaspaceUsed(); + for (int i = 0; i < maxIterations; i++) { + loadOneClass(); + long used = getMetaspaceUsed(); + if (used < prevUsed) { + System.out.println("GC detected at iteration " + i + + ", used dropped from " + prevUsed + " to " + used); + return; + } + prevUsed = used; + } + throw new RuntimeException("No metaspace GC after " + maxIterations + " class loads"); + } + + private static void loadOneClass() { + try { + String jarUrl = "file:" + (classCounter++) + ".jar"; + URLClassLoader cl = new URLClassLoader(new URL[]{new URL(jarUrl)}); + Proxy.newProxyInstance(cl, new Class[]{Dummy.class}, new DummyHandler()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static long getMetaspaceUsed() { + return java.lang.management.ManagementFactory.getMemoryPoolMXBeans().stream() + .filter(p -> p.getName().equals("Metaspace")) + .mapToLong(p -> p.getUsage().getUsed()) + .findFirst() + .orElseThrow(() -> new RuntimeException("Metaspace pool not found")); + } + + private static long parseSize(String size) { + size = size.toLowerCase(); + long multiplier = 1; + if (size.endsWith("m")) { + multiplier = 1024 * 1024; + size = size.substring(0, size.length() - 1); + } else if (size.endsWith("k")) { + multiplier = 1024; + size = size.substring(0, size.length() - 1); + } else if (size.endsWith("g")) { + multiplier = 1024 * 1024 * 1024; + size = size.substring(0, size.length() - 1); + } + return Long.parseLong(size) * multiplier; + } +} diff --git a/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java b/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java index 58f102298ff4..edafded07dc5 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java @@ -47,10 +47,10 @@ public static void testWith(String msg, boolean periodic, String... args) throws output.shouldHaveExitValue(0); if (periodic) { - output.shouldContain("Trigger: Time since last GC"); + output.shouldContain("Trigger: Guaranteed Interval."); } if (!periodic) { - output.shouldNotContain("Trigger: Time since last GC"); + output.shouldNotContain("Trigger: Guaranteed Interval."); } } @@ -63,11 +63,11 @@ public static void testGenerational(boolean periodic, String... args) throws Exc OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); if (periodic) { - output.shouldContain("Trigger (Young): Time since last GC"); - output.shouldContain("Trigger (Old): Time since last GC"); + output.shouldContain("Trigger (Young): Guaranteed Interval."); + output.shouldContain("Trigger (Old): Guaranteed Interval."); } else { - output.shouldNotContain("Trigger (Young): Time since last GC"); - output.shouldNotContain("Trigger (Old): Time since last GC"); + output.shouldNotContain("Trigger (Young): Guaranteed Interval."); + output.shouldNotContain("Trigger (Old): Guaranteed Interval."); } } diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index fe3c8a5a4763..7fd78e874c9c 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -91,7 +91,7 @@ public static void testOld(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(cmds); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); - output.shouldContain("Trigger (Old): Old has overgrown"); + output.shouldContain("Trigger (Old): Occupancy."); } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/gtest/ArrayTests.java b/test/hotspot/jtreg/gtest/ArrayTests.java index d3a8498d5ebf..2f470a293780 100644 --- a/test/hotspot/jtreg/gtest/ArrayTests.java +++ b/test/hotspot/jtreg/gtest/ArrayTests.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/gtest/ObjArrayTests.java b/test/hotspot/jtreg/gtest/ObjArrayTests.java index 67d994768f9c..238713965e50 100644 --- a/test/hotspot/jtreg/gtest/ObjArrayTests.java +++ b/test/hotspot/jtreg/gtest/ObjArrayTests.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/test/hotspot/jtreg/resourcehogs/compiler/arrays/TestFlatArrayMaximumLength.java b/test/hotspot/jtreg/resourcehogs/compiler/arrays/TestFlatArrayMaximumLength.java new file mode 100644 index 000000000000..2569c788c183 --- /dev/null +++ b/test/hotspot/jtreg/resourcehogs/compiler/arrays/TestFlatArrayMaximumLength.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.arrays; + +/** + * @test + * @bug 8391178 + * @summary Test correctness of C2's type for the length of large flat arrays + * @enablePreview + * @requires vm.compiler2.enabled & os.maxMemory > 4G + * @run main/othervm -Xmx4g -Xcomp -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+UseArrayFlattening -XX:+UseNullableAtomicValueFlattening + * -XX:CompileCommand=compileonly,${test.main.class}::test* + * ${test.main.class} + */ +public class TestFlatArrayMaximumLength { + + static value class EmptyValue { } + static final int[] smallArray = new int[2]; + static EmptyValue[] largeArray; + + static int test1() { + // C2 must preserve the normal return from this legal allocation + EmptyValue[] array = new EmptyValue[Integer.MAX_VALUE]; + largeArray = array; + return array.length; + } + + static void test2(int length) { + // The type of array.length is set to [0..Integer.MAX_VALUE-2] + // while it should be [0..Integer.MAX_VALUE] for a flat array. + EmptyValue[] array = new EmptyValue[length]; + // The range of index is therefore [0..1] but should be [0..2]. + int index = (array.length + 2) >>> 30; + // The range of index is still [0..1] but should be [0..4] now. + index = index * index; + // The range check will be removed here because [0..1] is always + // in range but that's incorrect because [0..4] is not in range. + // With length == Integer.MAX_VALUE, index is 4 and we fail to + // throw an exception and write beyond the end of the array. + smallArray[index] = 42; + } + + public static void main(String[] args) { + // Make sure that class is loaded + EmptyValue tmp = new EmptyValue(); + + if (test1() != Integer.MAX_VALUE) { + throw new RuntimeException("Incorrect array length"); + } + largeArray = null; + System.gc(); + + for (int i = 0; i < 30_000; i++) { + test2(1); + } + + try { + test2(Integer.MAX_VALUE); + throw new RuntimeException("No IndexOutOfBoundsException thrown!"); + } catch (IndexOutOfBoundsException expected) { + // Expected + } + } +} + diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java index e9bdbe308077..d4287d34294d 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java @@ -84,7 +84,6 @@ private static void do_test(boolean CDS) throws IOException { } output.shouldContain("Trying to reserve at an EOR-compatible address"); output.shouldNotContain(tryReserveForZeroBased); - output.shouldMatch(tryReserveFor16bitMoveIntoQ3Regex); } else if (Platform.isPPC()) { if (CDS) { output.shouldNotContain(tryReserveForUnscaled); diff --git a/test/hotspot/jtreg/runtime/Monitor/UseObjectMonitorTableTest.java b/test/hotspot/jtreg/runtime/Monitor/ObjectMonitorTableTest.java similarity index 95% rename from test/hotspot/jtreg/runtime/Monitor/UseObjectMonitorTableTest.java rename to test/hotspot/jtreg/runtime/Monitor/ObjectMonitorTableTest.java index fd6ece349a24..45d1f2370329 100644 --- a/test/hotspot/jtreg/runtime/Monitor/UseObjectMonitorTableTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/ObjectMonitorTableTest.java @@ -24,9 +24,9 @@ /** * @test id=NormalDeflation * @summary A collection of small tests using synchronized, wait, notify to try - * and achieve good cheap coverage of UseObjectMonitorTable. + * and achieve good cheap coverage of ObjectMonitorTable. * @library /test/lib - * @run main/othervm UseObjectMonitorTableTest + * @run main/othervm ObjectMonitorTableTest */ /** @@ -35,7 +35,7 @@ * @library /test/lib * @run main/othervm -XX:+UnlockDiagnosticVMOptions * -XX:GuaranteedAsyncDeflationInterval=1 - * UseObjectMonitorTableTest + * ObjectMonitorTableTest */ import jdk.test.lib.Utils; @@ -48,7 +48,7 @@ import java.util.Random; import java.util.stream.Stream; -public class UseObjectMonitorTableTest { +public class ObjectMonitorTableTest { static final ThreadFactory TF = Executors.defaultThreadFactory(); static class WaitNotifyTest implements Runnable { @@ -232,10 +232,10 @@ public static void main(String[] args) { try { t.join(); } catch (InterruptedException e) { - throw new RuntimeException("UseObjectMonitorTableTest: Unexpected interrupt", e); + throw new RuntimeException("ObjectMonitorTableTest: Unexpected interrupt", e); } }); - System.out.println("UseObjectMonitorTableTest passed."); + System.out.println("ObjectMonitorTableTest passed."); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/MultiReleaseJars.java b/test/hotspot/jtreg/runtime/cds/appcds/MultiReleaseJars.java index ac3672ce3fd8..0cf17980717f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/MultiReleaseJars.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/MultiReleaseJars.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ /* * @test MultiReleaseJars * @summary Test multi-release jar with AppCDS. + * @bug 8380847 * @requires vm.cds * @library /test/lib * @run main/othervm/timeout=2400 MultiReleaseJars @@ -34,8 +35,14 @@ import java.io.FileOutputStream; import java.io.PrintStream; import java.io.IOException; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.jar.Attributes.Name; + import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.cds.SimpleCDSAppTester; import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.util.JarUtils; public class MultiReleaseJars { @@ -60,7 +67,7 @@ static String[] getMain() { static String[] getVersion(int version) { String[] sts = { "package version;", - "public class Version {", + "class Version {", " public int getVersion(){ return " + version + "; }", "}" }; @@ -125,8 +132,9 @@ static void createClassFilesAndJar() throws Exception { JarBuilder.build("version", baseDir, metainf.getAbsolutePath(), "--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), "."); - // the following jar file is for testing case-insensitive "Multi-Release" - // attibute name + // version2.jar is exactly the same as version.jar, except that the manifest file contains + // "multi-Release" instead of "Multi-Release". This is for testing the case-insensitivity of + // the handling of attribute names. String[] meta2 = { "multi-Release: true", "Main-Class: version.Main" @@ -135,6 +143,23 @@ static void createClassFilesAndJar() throws Exception { writeFile(metainf, meta2); JarBuilder.build("version2", baseDir, metainf.getAbsolutePath(), "--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), "."); + + // version3.jar does not include version in the root directory and instead only has it + // in the version specific directory. A private version is used so as to avoid the JAR + // being rejected since there is no matching class in the root directory. + (new File(baseDir, "version/Version.class")).delete(); + writeFile(metainf, meta); + JarBuilder.build("version3", baseDir, metainf.getAbsolutePath(), + "--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), "."); + + // version4.jar is exactly the same as version3.jar, except that the manifest file contains + // "Multi-Release: truex" instead of "true". + Manifest manifest = new Manifest(); + try (JarFile jar = new JarFile("version3.jar")) { + manifest = jar.getManifest(); + } + manifest.getMainAttributes().put(Name.MULTI_RELEASE, "truex"); + JarUtils.updateManifest("version3.jar", "version4.jar", manifest); } static void checkExecOutput(OutputAnalyzer output, String expectedOutput) throws Exception { @@ -158,6 +183,8 @@ public static void main(String... args) throws Exception { String appClasses[] = {"version/Main", "version/Version"}; String appJar = TestCommon.getTestJar("version.jar"); String appJar2 = TestCommon.getTestJar("version2.jar"); + String appJar3 = TestCommon.getTestJar("version3.jar"); + String appJar4 = TestCommon.getTestJar("version4.jar"); String enableMultiRelease = "-Djdk.util.jar.enableMultiRelease=true"; String jarVersion = null; String expectedOutput = null; @@ -235,5 +262,66 @@ public static void main(String... args) throws Exception { output = TestCommon.exec(appJar2, mainClass); checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING); + + // 7. AOT Test + SimpleCDSAppTester.of("Multi-Release-AOT") + .addVmArgs("-Xlog:aot", + enableMultiRelease) + .classpath(appJar3) + .appCommandLine(mainClass) + .setTrainingChecker((OutputAnalyzer out) -> { + out.shouldNotMatch("class version/Version cannot be archived because it was not defined"); + }) + .setProductionChecker((OutputAnalyzer out) -> { + out.shouldContain("I am running on version " + MAJOR_VERSION_STRING); + }) + .runAOTWorkflow(); + + // 8. AOT Test with space after enableMultiRelease=true + SimpleCDSAppTester.of("Multi-Release-AOT") + .addVmArgs("-Xlog:aot", + enableMultiRelease + " ") + .classpath(appJar3) + .appCommandLine(mainClass) + .setTrainingChecker((OutputAnalyzer out) -> { + out.shouldNotMatch("class version/Version cannot be archived because it was not defined"); + }) + .setProductionChecker((OutputAnalyzer out) -> { + out.shouldContain("I am running on version " + MAJOR_VERSION_STRING); + }) + .runAOTWorkflow(); + + // 9. AOT Test with multi-release disabled + SimpleCDSAppTester.of("No-Multi-Release-AOT") + .setCheckExitValue(false) + .addVmArgs("-Xlog:aot", + "-Djdk.util.jar.enableMultiRelease=false") + .classpath(appJar3) + .appCommandLine(mainClass) + .setTrainingChecker((OutputAnalyzer out) -> { + out.shouldNotMatch("class version/Version cannot be archived because it was not defined"); + }) + .setProductionChecker((OutputAnalyzer out) -> { + out.shouldHaveExitValue(1); + out.shouldContain("java.lang.ClassNotFoundException: version.Version"); + }) + .runAOTWorkflow(); + + // 10. AOT Test with "Multi-Release: truex" instead of "true". The unexpected value + // is ignored and "true" is used by default + SimpleCDSAppTester.of("Multi-Release-AOT-Misspelled") + .setCheckExitValue(false) + .addVmArgs("-Xlog:aot", + enableMultiRelease) + .classpath(appJar4) + .appCommandLine(mainClass) + .setTrainingChecker((OutputAnalyzer out) -> { + out.shouldNotMatch("class version/Version cannot be archived because it was not defined"); + }) + .setProductionChecker((OutputAnalyzer out) -> { + out.shouldHaveExitValue(1); + out.shouldContain("java.lang.ClassNotFoundException: version.Version"); + }) + .runAOTWorkflow(); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java index 9fef0845d1df..66d9936f5ce0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java @@ -25,8 +25,9 @@ /* * @test * @summary Test AOT cache support for array classes in custom class loaders. - * @bug 8353298 8356838 + * @bug 8353298 8356838 8390471 * @requires vm.cds.supports.aot.class.linking + * @enablePreview * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build ReturnIntegerAsString * @build AOTCacheSupportForCustomLoaders @@ -60,12 +61,23 @@ public static void main(String... args) throws Exception { String modulePath = modulePackager.getOutputDir().toString(); modulePackager.createModularJar("com.test"); - SimpleCDSAppTester.of("AOTCacheSupportForCustomLoaders") + test(modulePath, false); + test(modulePath, true); // Test case for JDK-8390471 + } + + static void test(String modulePath, boolean preview) throws Exception { + SimpleCDSAppTester tester = SimpleCDSAppTester.of("AOTCacheSupportForCustomLoaders") .classpath("app.jar") .addVmArgs("-Xlog:aot+class=debug", "-Xlog:aot", "-Xlog:cds", "--module-path=" + modulePath, - "--add-modules=com.test") - .appCommandLine("AppWithCustomLoaders", modulePath) + "--add-modules=com.test"); + if (preview) { + // Test case for JDK-8390471 + tester.addVmArgs("--enable-preview", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+TestAOTAdapterLinkFailure"); // TestAOTAdapterLinkFailure is a developer flag + } + tester.appCommandLine("AppWithCustomLoaders", modulePath) .setTrainingChecker((OutputAnalyzer out) -> { out.shouldContain("Skipping AppWithCustomLoaders$MyLoadeeC: Not loaded from \"file:\" code source") .shouldContain("Skipping AppWithCustomLoaders$MyLoadeeD: super AppWithCustomLoaders$MyLoadeeC is excluded") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java index 718793902390..fc24f341ff36 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java @@ -101,7 +101,7 @@ static void positiveTests() throws Exception { "-XX:AOTMode=off", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldNotContain(", sharing"); + out.shouldNotContain(", aot production"); out.shouldNotContain("Opened AOT cache hello.aot."); out.shouldContain("Hello World"); out.shouldHaveExitValue(0); @@ -115,7 +115,7 @@ static void positiveTests() throws Exception { "-XX:AOTMode=auto", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain(", sharing"); + out.shouldContain(", aot production"); out.shouldContain("Opened AOT cache hello.aot."); out.shouldContain("Hello World"); out.shouldHaveExitValue(0); @@ -130,7 +130,7 @@ static void positiveTests() throws Exception { "-XX:AOTMode=" + mode, "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain(", sharing"); + out.shouldContain(", aot production"); out.shouldContain("Opened AOT cache hello.aot."); out.shouldContain("Hello World"); out.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java index e4d6a2e5d0f9..b131ebc4c8ee 100644 --- a/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java +++ b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java @@ -34,11 +34,16 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; public class StringTableCorruptionTest { + // Retain all Strings to make sure StringTable grows and keeps our corrupted String alive + static final List RETAIN = new ArrayList<>(); + public static void main(String[] args) throws Exception { if (args.length > 0) { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--add-opens", "java.base/java.lang=ALL-UNNAMED", @@ -51,9 +56,20 @@ public static void main(String[] args) throws Exception { Field f = String.class.getDeclaredField("value"); f.setAccessible(true); - f.set("s1".intern(), f.get("s2")); + + // Put a String into StringTable and corrupt it. + String s1 = "s1".intern(); + f.set(s1, f.get("s2")); + RETAIN.add(s1); + + // Fill in StringTable to trigger growth. + // Also do a few intentional GCs to make sure test behavior does not depend on accidental GCs. for (int i = 0; i < 4_000_000; i++) { - ("s_" + i).intern(); + String s = ("s_" + i).intern(); + RETAIN.add(s); + if (i % 100_000 == 0) { + System.gc(); + } } } } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/DirectMethodTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/DirectMethodTest.java index f4b6eb3634f4..b5b01a3786c2 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/DirectMethodTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/DirectMethodTest.java @@ -31,7 +31,7 @@ * @library /test/lib * @enablePreview * @compile --source 28 DirectMethodTest.java - * @run main/othervm -Djdk.reflect.useNativeAccessorOnly=true -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseArrayFlattening -XX:+UseFieldFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullableAtomicValueFlattening runtime.valhalla.inlinetypes.DirectMethodTest + * @run main/othervm -Djdk.reflect.useNativeAccessorOnly=true -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseArrayFlattening -XX:+UseFieldFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullableAtomicValueFlattening runtime.valhalla.inlinetypes.DirectMethodTest flat */ /* @@ -44,7 +44,7 @@ * @library /test/lib * @enablePreview * @compile --source 28 DirectMethodTest.java - * @run main/othervm -Djdk.reflect.useNativeAccessorOnly=true -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:-UseArrayFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullableAtomicValueFlattening runtime.valhalla.inlinetypes.DirectMethodTest + * @run main/othervm -Djdk.reflect.useNativeAccessorOnly=true -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:-UseArrayFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullableAtomicValueFlattening runtime.valhalla.inlinetypes.DirectMethodTest noflat */ package runtime.valhalla.inlinetypes; @@ -52,20 +52,17 @@ import java.lang.reflect.Array; import java.lang.reflect.Method; import jdk.internal.value.ValueClass; - +import jdk.test.lib.Asserts; public class DirectMethodTest { + static boolean expectFlat = false; public int method1(int i, int j, int k) { - System.out.println("i = " + i + " j = " + j + " k = " + k); return i + j * k; } - public static void printFlat(Object[] array) { - if (!ValueClass.isFlatArray(array)) { - System.out.println("not flat " + array); - } else { - System.out.println("yay flat " + array); - } + public static void checkFlat(Object[] array) { + boolean isFlat = ValueClass.isFlatArray(array); + Asserts.assertEquals(expectFlat, isFlat); } static value class SmallValue { @@ -76,30 +73,34 @@ static value class SmallValue { } public int method2(SmallValue i, SmallValue j, SmallValue k) { - System.out.println("i = " + i + " j = " + j + " k = " + k); return i.s + j.s * k.s; } static final int ARRAY_SIZE = 3; - public static void main(java.lang.String[] unused) throws Exception { + public static void main(String[] args) throws Exception { + expectFlat = args[0].equals("flat"); DirectMethodTest d = new DirectMethodTest(); Method m = DirectMethodTest.class.getMethod("method1", int.class, int.class, int.class); Integer[] intarray = new Integer[]{1, 2, 3}; // is this flattened? - printFlat(intarray); + checkFlat(intarray); Object[] array = (Object[])Array.newInstance(Integer.class, 3); - printFlat(array); + checkFlat(array); array = ValueClass.newNullableAtomicArray(Integer.class, ARRAY_SIZE); - printFlat(array); - System.out.println("value is " + m.invoke(d, 1, 2, 3)); + checkFlat(array); + if (!m.invoke(d, 1, 2, 3).equals(7)) { + throw new RuntimeException("Unexpected method1 result"); + } Method m2 = DirectMethodTest.class.getMethod("method2", SmallValue.class, SmallValue.class, SmallValue.class); Object[] smallValueArray = (Object[])Array.newInstance(SmallValue.class, ARRAY_SIZE); - printFlat(smallValueArray); + checkFlat(smallValueArray); smallValueArray = ValueClass.newNullableAtomicArray(SmallValue.class, ARRAY_SIZE); - printFlat(smallValueArray); - System.out.println("value is " + m2.invoke(d, new SmallValue((short)1), new SmallValue((short)2), new SmallValue((short)3))); + checkFlat(smallValueArray); + if (!m2.invoke(d, new SmallValue((short)1), new SmallValue((short)2), new SmallValue((short)3)).equals(7)) { + throw new RuntimeException("Unexpected method1 result"); + } } } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValueObjectMethodsInit.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValueObjectMethodsInit.java new file mode 100644 index 000000000000..dedbe4be227b --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValueObjectMethodsInit.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary Test ValueObjectMethods class initialization + * @bug 8391022 + * @requires vm.cds.supports.aot.class.linking + * @comment DeoptimizeALot flag requires debug VM + * @requires vm.debug + * @library /test/lib + * @enablePreview + * @modules java.base/jdk.internal.value + * @build TestValueObjectMethodsInit + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar + * ValueObjectMethodsClassApp + * ValueObjectMethodsClassApp$Value + * @run driver TestValueObjectMethodsInit + */ + +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestValueObjectMethodsInit { + public static void main(String[] args) throws Exception { + final String appJar = ClassFileInstaller.getJarPath("app.jar"); + final String aotConfigFile = "app.aotconfig"; + final String aotCacheFile = "app.aot"; + final String appClass = "ValueObjectMethodsClassApp"; + + ProcessBuilder pb; + OutputAnalyzer out; + + // first make sure we have a valid aotConfigFile + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "--enable-preview", + "-XX:CompileThresholdScaling=0.01", + "-Xlog:aot", + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, appClass); + + out = CDSTestUtils.executeAndLog(pb, "train"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "--enable-preview", + "-Xlog:aot", + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar); + + out = CDSTestUtils.executeAndLog(pb, "assemble"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "--enable-preview", + "-XX:CompileThresholdScaling=0.01", + "-XX:+DeoptimizeALot", + "-Xlog:aot", + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar, appClass); + + out = CDSTestUtils.executeAndLog(pb, "production"); + out.shouldHaveExitValue(0); + } +} + +class ValueObjectMethodsClassApp { + private static int hash; + + static value class Value { + private final int val; + Value(int i) { + val = i; + } + } + + static int test(int i) { + return System.identityHashCode(new Value(i)); + } + + public static void main(String[] args) { + // 1000 iterations are enough since we use CompileThresholdScaling=0.01 + for (int i = 0; i < 1000; i++) { + hash = test(i); + } + System.out.println("Hash: " + hash); + } +} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewApp.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewApp.jasm new file mode 100644 index 000000000000..698332456b6f --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewApp.jasm @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +final identity class EarlyLarvalNonPreviewApp extends java/lang/Record version 72:0 +{ + public final Field x:I; + public final Field y:I; + + public Method "":"(II)V" + stack 2 locals 3 + 0: #{ x } + 1: #{ y } + { + aload_0; + invokespecial Method java/lang/Record."":"()V"; + aload_0; + iload_1; + putfield Field x:"I"; + iload_1; + ifge L16; + iload_2; + ineg; + istore_2; + L16: stack_frame_type early_larval; + unset_fields; + frame_type full; + locals_map class EarlyLarvalNonPreviewApp, int, int; + stack_map; + aload_0; + iload_2; + putfield Field y:"I"; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewTest.java similarity index 54% rename from test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewTest.java index fe8777eed862..79d474620898 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EarlyLarvalNonPreviewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,24 +21,26 @@ * questions. */ - /* * @test - * @modules java.base/jdk.internal.misc:+open - * - * @summary converted from VM Testbase metaspace/gc/firstGC_99m. - * VM Testbase keywords: [nonconcurrent, quarantine] - * VM Testbase comments: 8208250 - * - * @library /vmTestbase /test/lib - * @run main/othervm - * -Xms200m - * -Xlog:gc+heap=trace,gc:gc.log - * -XX:MetaspaceSize=99m - * -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions - * -XX:-VerifyBeforeExit - * -XX:-UseCompressedOops - * metaspace.gc.FirstGCTest + * @enablePreview + * @library /test/lib + * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value + * @compile EarlyLarvalNonPreviewApp.jasm + * @run main EarlyLarvalNonPreviewTest */ +public class EarlyLarvalNonPreviewTest { + public static void main(String[] args) { + try { + var value = new EarlyLarvalNonPreviewApp(-1, -2); + throw new RuntimeException("Expected ClassFormatError"); + } catch (ClassFormatError c) { + if (!c.getMessage().equals("StackMapTable format error: reserved frame type")) { + throw new RuntimeException("Unexpected ClassFormatError " + c.getMessage()); + } + System.out.println("Test passed"); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/libsuspendthrd01.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/libsuspendthrd01.cpp deleted file mode 100644 index 053023529cdc..000000000000 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/libsuspendthrd01.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ - -#include -#include "jvmti.h" -#include "jvmti_common.hpp" -#include "jvmti_thread.hpp" - -extern "C" { - -/* ============================================================================= */ - -/* scaffold objects */ -static jlong timeout = 0; - -/* constant names */ -#define THREAD_NAME "TestedThread" - -/* ============================================================================= */ - -/** Agent algorithm. */ -static void JNICALL -agentProc(jvmtiEnv *jvmti, JNIEnv *jni, void *arg) { - - LOG("Wait for thread to start\n"); - if (!agent_wait_for_sync(timeout)) - return; - - /* perform testing */ - { - LOG("Find thread: %s\n", THREAD_NAME); - jthread tested_thread = find_thread_by_name(jvmti, jni, THREAD_NAME); - if (tested_thread == nullptr) { - return; - } - LOG(" ... found thread: %p\n", (void *) tested_thread); - - LOG("Suspend thread: %p\n", (void *) tested_thread); - suspend_thread(jvmti, jni, tested_thread); - - LOG("Let thread to run and finish\n"); - if (!agent_resume_sync()) { - return; - } - - LOG("Get state vector for thread: %p\n", (void *) tested_thread); - { - jint state = get_thread_state(jvmti, jni, tested_thread); - LOG(" ... got state vector: %s (%d)\n", TranslateState(state), (int) state); - - if ((state & JVMTI_THREAD_STATE_SUSPENDED) == 0) { - LOG("SuspendThread() does not turn on flag SUSPENDED:\n" - "# state: %s (%d)\n", TranslateState(state), (int) state); - set_agent_fail_status(); - } - } - - LOG("Resume thread: %p\n", (void *) tested_thread); - resume_thread(jvmti, jni, tested_thread); - - LOG("Wait for thread to finish\n"); - if (!agent_wait_for_sync(timeout)) { - return; - } - - LOG("Delete thread reference\n"); - jni->DeleteGlobalRef(tested_thread); - } - - LOG("Let debugee to finish\n"); - if (!agent_resume_sync()) { - return; - } -} - -/* ============================================================================= */ - -JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { - jvmtiEnv *jvmti = nullptr; - - timeout = 60 * 1000; - - jint res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_9); - if (res != JNI_OK || jvmti == nullptr) { - LOG("Wrong result of a valid call to GetEnv!\n"); - return JNI_ERR; - } - - /* add specific capabilities for suspending thread */ - - jvmtiCapabilities caps; - memset(&caps, 0, sizeof(caps)); - caps.can_suspend = 1; - if (jvmti->AddCapabilities(&caps) != JVMTI_ERROR_NONE) { - return JNI_ERR; - } - - - if (init_agent_data(jvmti, &agent_data) != JVMTI_ERROR_NONE) { - return JNI_ERR; - } - - /* register agent proc and arg */ - if (!set_agent_proc(agentProc, nullptr)) { - return JNI_ERR; - } - - return JNI_OK; -} - -} diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/suspendthrd01.java b/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/suspendthrd01.java index 40649965b547..eb505c430bc8 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/suspendthrd01.java +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/SuspendThread/suspendthrd01/suspendthrd01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,66 +35,39 @@ * Modified due to fix of the RFE * 5001769 TEST_RFE: remove usage of deprecated GetThreadStatus function * - * @library /test/lib - * @run main/othervm/native -agentlib:suspendthrd01=-waittime=5 suspendthrd01 + * @library /test/lib /test/hotspot/jtreg/testlibrary + * @run main/othervm/native suspendthrd01 */ -import jdk.test.lib.jvmti.DebugeeClass; +import jvmti.JVMTIUtils; -public class suspendthrd01 extends DebugeeClass { - - // load native library if required - static { - System.loadLibrary("suspendthrd01"); - } +public class suspendthrd01 { // run test from command line public static void main(String argv[]) { - new suspendthrd01().runIt(argv); - } - - /* =================================================================== */ - - long timeout = 0; - int status = DebugeeClass.TEST_PASSED; - - // run debuggee - public void runIt(String argv[]) { - timeout = 60 * 1000; // milliseconds - - // create tested thread suspendthrd01Thread thread = new suspendthrd01Thread("TestedThread"); - - // run tested thread - System.out.println("Staring tested thread"); + System.out.println("Starting tested thread"); + thread.start(); + if (!thread.checkReady()) { + throw new RuntimeException("Unable to prepare tested thread: " + thread); + } + JVMTIUtils.suspendThread(thread); try { - thread.start(); - if (!thread.checkReady()) { - throw new RuntimeException("Unable to prepare tested thread: " + thread); + // the suspended thread cannot see the flag and must not finish + thread.letFinish(); + int state = JVMTIUtils.getThreadState(thread); + if ((state & JVMTIUtils.JVMTI_THREAD_STATE_SUSPENDED) == 0) { + throw new RuntimeException("Thread is not in the suspended state: " + state); } - - // testing sync - System.out.println("Sync: thread started"); - status = checkStatus(status); } finally { - // let thread to finish - thread.letFinish(); + JVMTIUtils.resumeThread(thread); } - - // wait for thread to finish System.out.println("Finishing tested thread"); try { thread.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } - - // testing sync - System.out.println("Sync: thread finished"); - status = checkStatus(status); - if (checkStatus(status) != 0) { - new RuntimeException(); - } } } diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java index de64706a8967..441f63d9246b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -152,7 +152,8 @@ private void runTest(String[] args) { pthread.waitReady(); // We are ready. - LingeredApp.main(args); + // Run the app on the current thread, the scheduler is limited to one carrier. + LingeredApp.mainLoop(args); } finally { // Signal all threads to finish. diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java index 6493a803e90f..ac5986714f78 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java @@ -58,7 +58,7 @@ public static void main(String[] args) throws Exception { "detach", "universe", "reattach", - "longConstant markWord::locked_value"); + "longConstant markWord::fast_locked_value"); Map> expStrMap = new HashMap<>(); expStrMap.put("where", List.of( @@ -67,8 +67,8 @@ public static void main(String[] args) throws Exception { "MaxJavaStackTraceDepth = ")); expStrMap.put("universe", List.of( "Command not valid until attached to a VM")); - expStrMap.put("longConstant markWord::locked_value", List.of( - "longConstant markWord::locked_value")); + expStrMap.put("longConstant markWord::fast_locked_value", List.of( + "longConstant markWord::fast_locked_value")); test.run(-1, cmds, expStrMap, null); } catch (SkippedException se) { diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java index 1c8cf7191dd2..36f4d9cf2fcd 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java @@ -109,7 +109,7 @@ public static void runAllTypesTest() throws Exception { "-XX:NativeMemoryTracking=off", // ccstr "-XX:OnError='echo error'", // ccstrlist "-XX:CompileThresholdScaling=1.0", // double - "-XX:ErrorLogTimeout=120"); // uint64_t + "-XX:MaxDirectMemorySize=4294967297"); // uint64_t theApp = new LingeredApp(); LingeredApp.startAppExactJvmOpts(theApp, vmArgs); System.out.println("Started LingeredApp with pid " + theApp.getPid()); @@ -127,7 +127,7 @@ public static void runAllTypesTest() throws Exception { "NativeMemoryTracking = \"off\"", "OnError = \"'echo error'\"", "CompileThresholdScaling = 1.0", - "ErrorLogTimeout = 120")); + "MaxDirectMemorySize = 4294967297")); test.run(theApp.getPid(), cmds, expStrMap, null); } catch (Exception ex) { diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index d6f957d4a3a0..9705c9574d3d 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -53,18 +53,18 @@ public static void main(String[] args) throws Exception { List cmds = List.of( "longConstant", - "longConstant markWord::locked_value", + "longConstant markWord::fast_locked_value", "longConstant markWord::lock_bits", "longConstant jtreg::test 6", "longConstant jtreg::test"); Map> expStrMap = new HashMap<>(); expStrMap.put("longConstant", List.of( - "longConstant markWord::locked_value", + "longConstant markWord::fast_locked_value", "longConstant markWord::lock_bits", "InvocationCounter::count_increment")); - expStrMap.put("longConstant markWord::locked_value", List.of( - "longConstant markWord::locked_value")); + expStrMap.put("longConstant markWord::fast_locked_value", List.of( + "longConstant markWord::fast_locked_value")); expStrMap.put("longConstant markWord::lock_bits", List.of( "longConstant markWord::lock_bits")); expStrMap.put("longConstant jtreg::test", List.of( diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index d9facb130789..6c81db9e0ab8 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -323,6 +323,7 @@ private String[] cmd(long classStart, long classStop) { "-XX:+StressMacroExpansion", "-XX:+StressMacroElimination", "-XX:+StressIncrementalInlining", + "-XX:+StressVerifyMeetJoin", // StressSeed is uint "-XX:StressSeed=" + rng.nextInt(Integer.MAX_VALUE), // Do not fail on huge methods where StressGCM makes register diff --git a/test/hotspot/jtreg/testlibrary/jvmti/JVMTIUtils.java b/test/hotspot/jtreg/testlibrary/jvmti/JVMTIUtils.java index b2224b90365c..8833921c41db 100644 --- a/test/hotspot/jtreg/testlibrary/jvmti/JVMTIUtils.java +++ b/test/hotspot/jtreg/testlibrary/jvmti/JVMTIUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,8 @@ public class JVMTIUtils { public static int JVMTI_ERROR_WRONG_PHASE = 112; + public static int JVMTI_THREAD_STATE_SUSPENDED = 0x100000; + public static class JvmtiException extends RuntimeException { private int code; @@ -82,4 +84,6 @@ public static void resumeThread(Thread t) { } } + public static native int getThreadState(Thread t); + } diff --git a/test/hotspot/jtreg/testlibrary/jvmti/libJvmtiUtils.cpp b/test/hotspot/jtreg/testlibrary/jvmti/libJvmtiUtils.cpp index a5b2b268ff15..610a92f0351d 100644 --- a/test/hotspot/jtreg/testlibrary/jvmti/libJvmtiUtils.cpp +++ b/test/hotspot/jtreg/testlibrary/jvmti/libJvmtiUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,4 +69,12 @@ Java_jvmti_JVMTIUtils_resumeThread0(JNIEnv *jni, jclass cls, jthread thread) { return jvmti->ResumeThread(thread); } +JNIEXPORT jint JNICALL +Java_jvmti_JVMTIUtils_getThreadState(JNIEnv *jni, jclass cls, jthread thread) { + jint state = 0; + jvmtiError err = jvmti->GetThreadState(thread, &state); + check_jvmti_status(jni, err, "Error during GetThreadState()"); + return state; +} + } diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java index 1f176efff0f9..f1bf34be0495 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * 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,31 +23,92 @@ package ir_framework.tests; -import compiler.lib.ir_framework.IR; -import compiler.lib.ir_framework.IRNode; -import compiler.lib.ir_framework.Test; -import compiler.lib.ir_framework.TestFramework; +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; /* * @test * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless * @summary Sanity test remaining framework property/D flags with non-default values. We do two runs, one time with * VerifyIR=false and one time with VerifyIR=true. * @library /test/lib / - * @run main/othervm -DFlipC1C2=true -DExcludeRandom=true -DVerifyVM=true -DDumpReplay=true -DVerbose=true - * -DShuffleTests=false -DReproduce=true -DReportStdout=true -DGCAfter=true -DPrintTimes=true - * -DIgnoreCompilerControls=true -DExcludeRandom=true -DVerifyIR=true - * -DPreferCommandLineFlags=true -DPrintRuleMatchingTime=true ir_framework.tests.TestDFlags - * @run main/othervm -DFlipC1C2=true -DExcludeRandom=true -DVerifyVM=true -DDumpReplay=true -DVerbose=true - * -DShuffleTests=false -DReproduce=true -DReportStdout=true -DGCAfter=true -DPrintTimes=true - * -DIgnoreCompilerControls=true -DExcludeRandom=true -DVerifyIR=false - * -DPreferCommandLineFlags=true -DPrintRuleMatchingTime=true ir_framework.tests.TestDFlags + * @run driver ${test.main.class} spawn */ public class TestDFlags { - public static void main(String[] args) { - TestFramework.run(); + public static void main(String[] args) throws Exception { + if (args.length > 0) { + try { + // We pass all non-default except for VerifyIR: + execute("-DFlipC1C2=true", + "-DExcludeRandom=true", + "-DVerifyVM=true", + "-DDumpReplay=true", + "-DVerbose=true", + "-DShuffleTests=false", + "-DReportStdout=true", + "-DGCAfter=true", + "-DPrintTimes=true", + "-DIgnoreCompilerControls=true", + "-DVerifyIR=true", // default -> apply IR verification + "-DPreferCommandLineFlags=true"); + + execute("-DFlipC1C2=true", + "-DExcludeRandom=true", + "-DVerifyVM=true", + "-DDumpReplay=true", + "-DVerbose=true", + "-DShuffleTests=false", + "-DReportStdout=true", + "-DGCAfter=true", + "-DPrintTimes=true", + "-DIgnoreCompilerControls=true", + "-DVerifyIR=false", // non-default -> no IR verification + "-DPreferCommandLineFlags=true"); + } finally { + deleteReplayFiles(); + } + } else { + TestFramework.run(); + } } + private static void execute(String... propertyFlags) throws Exception { + // Property flags are usually added as additionally options when running a jtreg test. To simulate that, we + // explicitly need to set the -Dtest.java.opts to propagate them to the Test VM. When we only specify the + // property flags in '@run main/othervm', they are not passed to the Test VM. + List command = new ArrayList<>(); + // Set jtreg set properties explicitly since we spawn a separate VM + command.add("-Dtest.class.path=" + Utils.TEST_CLASS_PATH); + command.add("-Dtest.jdk=" + Utils.TEST_JDK); + + command.add("-Dtest.java.opts=" + String.join(" ", propertyFlags)); // Properties for Test VM + command.addAll(List.of(propertyFlags)); // Properties for Driver VM + command.add(TestDFlags.class.getName()); + ProcessTools.executeTestJava(command).shouldHaveExitValue(0); + } + + // Clean up the many replay files generated by using -DDumpReplay=true. + private static void deleteReplayFiles() { + Path scratchDir = Path.of(System.getProperty("user.dir")); + + try (DirectoryStream files = Files.newDirectoryStream(scratchDir, "replay_pid*_compid*.log")) { + for (Path file : files) { + Files.deleteIfExists(file); + } + } catch (IOException e) { + throw new RuntimeException("Could not delete replay files from " + scratchDir, e); + } + } + + @Test @IR(failOn = IRNode.STORE) public int c1() { @@ -75,5 +136,40 @@ public void c2_3() { for (int i = 0; i < 100; i++) { } } + + @Test + @IR(failOn = IRNode.STORE) + public void test1() { + } + + @Run(test = "test1") + public void runTest1() { + test1(); + } + + @Test + @IR(failOn = IRNode.STORE) + public void test2() { + } + + @Check(test = "test2") + public void checkTest2() { + } + + @Test + @IR(failOn = IRNode.STORE) + public void test3() { + } + + @Test + @IR(failOn = IRNode.STORE) + public void test4() { + } + + @Run(test = {"test3", "test4"}) + public void runTest3And4() { + test3(); + test4(); + } } diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java index 8e87985e3d30..54eb01f8b3bf 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java @@ -48,6 +48,7 @@ import static compiler.lib.template_framework.Template.let; import compiler.lib.template_framework.library.Expression; import compiler.lib.template_framework.library.Operations; +import compiler.lib.template_framework.library.ShortCarriesFloat16Type; import compiler.lib.template_framework.library.TestFrameworkClass; public class TestExpressions { @@ -88,6 +89,12 @@ public static String generate(CompileFramework comp) { // precision results from some operators. We only compare the results if we know that the // result is deterministically the same. TemplateToken expressionToken = expression.asToken(expression.argumentTypes.stream().map(t -> t.con()).toList()); + // Float16Vector lane()/reduceLanes() return a short carrier; box to Float16 so + // Verify.checkEQ canonicalizes NaN. + boolean float16CarrierResult = expression.returnType instanceof ShortCarriesFloat16Type; + List returnStmt = float16CarrierResult + ? List.of("return Float16.shortBitsToFloat16(", expressionToken, ");\n") + : List.of("return ", expressionToken, ";\n"); return scope( let("returnType", expression.returnType), """ @@ -104,7 +111,7 @@ public static String generate(CompileFramework comp) { public static Object ${primitiveConTest}_compiled() { try { """, - "return ", expressionToken, ";\n", + returnStmt, expression.info.exceptions.stream().map(exception -> "} catch (" + exception + " e) { return e;\n" ).toList(), @@ -118,7 +125,7 @@ public static String generate(CompileFramework comp) { public static Object ${primitiveConTest}_reference() { try { """, - "return ", expressionToken, ";\n", + returnStmt, expression.info.exceptions.stream().map(exception -> "} catch (" + exception + " e) { return e;\n" ).toList(), diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/weak005.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/weak005.java index c1593aea9799..9895204e8e86 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/weak005.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/weak005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import jdk.test.whitebox.WhiteBox; import nsk.share.gc.*; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; /** @@ -56,23 +57,24 @@ class Worker implements Runnable { private int length = 10000; private int objectSize = 10000; private WeakReference[] references; + private WeakReference lastReference; public Worker() { System.out.println("Array size: " + length); System.out.println("Object size: " + objectSize); - references = new WeakReference[length]; } private void makeReferences() { - references[length - 1] = null; MemoryObject obj = new MemoryObject(objectSize); + references = new WeakReference[length]; references[0] = new WeakReference(obj); for (int i = 1; i < length; ++i) { references[i] = new WeakReference(references[i - 1]); } - for (int i = 0; i < length - 1; ++i) { - references[i] = null; - } + lastReference = references[length - 1]; + // Drop all strong references to the chain in one write. + references = null; + Reference.reachabilityFence(obj); } public void run() { @@ -81,7 +83,7 @@ public void run() { if (!getExecutionController().continueExecution()) { return; } - if (references[length - 1].get() != null) { + if (lastReference.get() != null) { log.error("Last weak reference has not been cleared"); setFailed(true); } diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/FirstGCTest.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/FirstGCTest.java deleted file mode 100644 index 517a2066d641..000000000000 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/FirstGCTest.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 metaspace.gc; - -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import static metaspace.gc.MetaspaceBaseGC.PAGE_SIZE; - -/** - * Test for metaspace GC - * - *
    - *
  • MetaspaceSize - *
- * Test checks that the first GC happens when metaspace committed is next to - * MetaspaceSize value. - * - * Based on actual events (JDK 8 GC tuning document) - * - * Quating: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning - *
- * Class metadata is deallocated when the corresponding Java class is unloaded.
- * Java classes are unloaded as a results of garbage collection and garbage
- * collections may be induced in order to unload classes and deallocate class
- * metadata. When the space used for class metadata reaches a certain level
- * (call it a high-water mark), a garbage collection is induced.
- *
- * The flag MetaspaceSize can be set higher to avoid early garbage collections
- * induced for class metadata. The amount of class metadata allocated for
- * an application is application dependent and general guidelines do not
- * exist for the selection of MetaspaceSize. The default size of MetaspaceSize
- * is platform dependent and ranges from 12 MB to about 20 MB.
- * 
- */ -public class FirstGCTest extends MetaspaceBaseGC { - /** - * Current amount of the used metaspace - */ - protected long used = 0; - - /** - * Current amount of the committed metaspace - */ - protected long committed = 0; - - /** - * Previous amount of the used metaspace - */ - protected long p_used = 0 ; - - /** - * Previous amount of the committed metaspace - */ - protected long p_committed = 0; - - public static void main(String... args) { - new FirstGCTest().run(args); - } - - // value given in -XX:metaspaceSize= - private long metaspaceSize = -1; - - - @Override - protected void parseArgs(String[] args) { - final String XXSize = "-XX:MetaspaceSize="; - for (String va: vmArgs) { - if (va.startsWith(XXSize)) { - metaspaceSize = parseValue(va.substring(XXSize.length())); - } - } - } - - @Override - protected String getPoolName() { - return "Metaspace"; - } - - /** - * Check for the first GC moment. - * - * Eats memory until GC is invoked (amount of used metaspace became less); - * Checks that committed memory is close to MemaspaceSize. - * Eats memory until the second GC to check min/max ratio options have effect. - */ - @Override - public void doCheck() { - int gcCount = super.getMetaspaceGCCount(); - if (gcCount == 0) { - // gc hasn't happened yet. Start loading classes. - boolean gcHappened = this.eatMemoryUntilGC(50000); - if (!gcHappened) { - throw new Fault("GC hasn't happened"); - } - System.out.println("% GC: " + super.lastGCLogLine()); - System.out.println("% used : " + p_used + " --> " + used); - System.out.println("% committed: " + p_committed + " --> " + committed); - checkCommitted(p_committed); - } else { - // everything has happened before - checkCommitted(detectCommittedFromGCLog()); - } - } - - /** - * Check that committed amount is close to expected value (MetaspaceSize) - * - * @param committedAmount - value to check - */ - void checkCommitted(long committedAmount) { - if (metaspaceSize > 0) { - // -XX:MetaspaceSize is given - if (Math.abs((int) (metaspaceSize - committedAmount)) < PAGE_SIZE) { - System.out.println("% GC happened at the right moment"); - return; - } - if (!isMetaspaceGC()) { - System.out.println("% GC wasn't induced by metaspace, cannot check the moment :("); - return; - } - System.err.println("%## GC happened at the wrong moment, " - + "the amount of committed space significantly differs " - + "from the expected amount"); - System.err.println("%## Real : " + committedAmount); - System.err.println("%## Expected: " + metaspaceSize); - throw new Fault("GC happened at the wrong moment"); - } else { - // -XX:MetaspaceSize is not given, check for default values - if (11_500_000 < committedAmount && committedAmount < 22_500_000) { - System.out.println("% GC happened when the committed amout was from 12 MB to about 20 MB."); - return; - } - if (!isMetaspaceGC()) { - System.out.println("% GC wasn't induced by metaspace, this is excuse"); - return; - } - System.err.println("%## GC happened at the wrong moment, " - + "the amount of committed space was expected from 12 MB to about 20 MB"); - System.err.println("%## Real : " + committedAmount); - throw new Fault("It was the wrong moment when GC happened"); - } - } - - /** - * Load new classes without keeping references to them trying to provoke GC. - * Stops if GC is detected, or number of attempts exceeds the given limit. - * - * @param times limit of attempts to provoke GC - * @return true if GC has happened, false if limit has exceeded. - */ - protected boolean eatMemoryUntilGC(int times) { - System.out.println("%%%% Loading classes"); - System.out.println("% iter# : used : commited"); - System.out.println(".............................."); - for (int i = 1; i < times; i++) { - loadNewClasses(1, false); - if (i % 1000 == 0) { - printMemoryUsage("% " + i + " "); - } - p_used = used; - p_committed = committed; - used = getUsed(); - committed = getCommitted(); - - if (used < p_used) { - return true; - } - } - return false; - } - - /** - * If the first full GC has already happened we will try to detect - * the committed amount from the gc.log file. - * - * @return committed amount detected - * @throws Fault if failed to detect. - */ - protected long detectCommittedFromGCLog() { - // parse gc.log to extract the committed value from string like: - // Metaspace used 10133K, capacity 10190K, committed 10240K, reserved 10240Kl - System.out.println("%%%% Parsing gc log to detect the moment of the first GC"); - String format = ".*Metaspace.* used .*, capacity .*, committed (\\d+)([KMGkmg]), reserved .*"; - Pattern p = Pattern.compile(format); - try { - for (String line: readGCLog()) { - Matcher m = p.matcher(line); - if (m.matches()) { - int amount = Integer.parseInt(m.group(1)); - int multi = 1; - switch (m.group(2).toLowerCase()) { - case "k": multi = 1024; break; - case "m": multi = 1024*1024; break; - case "g": multi = 1024*1024*1024; break; - } - long value = amount * multi; - System.out.println("% Committed detected: " + value); - return value; - } - } - } catch (IOException e) { - throw new Fault("Cannot read from the GC log"); - } - System.out.println("% String that matches pattern '" + format + "' not found in the GC log file."); - throw new Fault("Unable to detect the moment of GC from log file"); - } - -} diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java index 244431100f7b..e819247a7a2e 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,12 @@ * If it is less than MinMetaspaceFreeRatio, the high-water mark will be raised. * */ -public class HighWaterMarkTest extends FirstGCTest { +public class HighWaterMarkTest extends MetaspaceBaseGC { + + @Override + protected String getPoolName() { + return "Metaspace"; + } public static void main(String... args) { new HighWaterMarkTest().run(args); diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TEST.properties b/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TEST.properties deleted file mode 100644 index 3d748e1ab1f7..000000000000 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TEST.properties +++ /dev/null @@ -1 +0,0 @@ -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TEST.properties b/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TEST.properties deleted file mode 100644 index 3d748e1ab1f7..000000000000 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_50m/TEST.properties +++ /dev/null @@ -1 +0,0 @@ -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TEST.properties b/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TEST.properties deleted file mode 100644 index 3d748e1ab1f7..000000000000 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_99m/TEST.properties +++ /dev/null @@ -1 +0,0 @@ -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TEST.properties b/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TEST.properties deleted file mode 100644 index 3d748e1ab1f7..000000000000 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TEST.properties +++ /dev/null @@ -1 +0,0 @@ -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/readme.txt b/test/hotspot/jtreg/vmTestbase/metaspace/gc/readme.txt index b1f337d251ca..214a6c0ff35a 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/readme.txt +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/readme.txt @@ -25,16 +25,12 @@ metaspace/gc tests - are the test for the Metaspace GC tuning, which is describe Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning Tests load classes and monitor the used/committed amounts of metaspace. -There are three types of tests all extending base class - MetaspaceBaseGC +There are two types of tests all extending base class - MetaspaceBaseGC MemoryUsageTest - trivial test to check memory dynamic (loading classes should lead to growth of used memory, gc to reduce) -FirstGCTest - - loads classes until the GC has happened and check the GC has happened at the - right moment (as stated in the Spec) - HighWaterMarkTest The test loads classes until the committed metaspace achieves the certain level between MetaspaceSize and MaxMetaspaceSize. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java index e090f357b4cd..5e8b57a4c6ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java @@ -105,6 +105,8 @@ protected void runCases() { Paragrep grep; String found; String[] threads; + String[] mainThreads; + String mainThread; jdb.setBreakpointInMethod(LAST_BREAK); waitForTestedThreadStarts(THREAD_STARTED_BREAK, numThreads); @@ -119,6 +121,23 @@ protected void runCases() { pauseTillAllThreadsWaiting(threads); + mainThreads = jdb.getThreadIdsByName("main"); + if (mainThreads.length != 1) { + log.complain("Failed to properly find one main thread: " + mainThreads.length); + success = false; + } + mainThread = mainThreads[0]; + + // Right now all threads are suspended. Before doing the interrupts we need to + // resume all threads except for the main thread. Otherwise, in the case of + // virtual threads, we can get a deadlock. To accomplish this we issue a + // "suspend" on the main thread so its suspend count is one higher than all + // the other threads, and then we "resume" on all threads, which should resume + // every thread except for the main thread. + reply = jdb.receiveReplyFor(JdbCommand.suspend + mainThread); + reply = jdb.receiveReplyFor(JdbCommand.resume, false); // don't expect a compound prompt + reply = jdb.receiveReplyFor(JdbCommand.thread + mainThread); // get compound prompt back + for (int i = 0; i < threads.length; i++) { reply = jdb.receiveReplyFor(JdbCommand.interrupt + threads[i]); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java index d945672439fd..1659241ead5a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java @@ -133,11 +133,7 @@ private int runThis (String argv[], PrintStream out) { Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java index eb4569cda0bc..cc4c1f334d3d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java @@ -50,7 +50,6 @@ * nsk.jdi.Accessible.isPrivate.isPrivate001a * @run driver * nsk.jdi.Accessible.isPrivate.isPrivate001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java index 163b687a9827..836f6d4ec15b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isPrivate001 JDI test. */ public class isPrivate001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -82,31 +81,18 @@ private static class s_interf_impl implements s_interf {} pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isPrivate001a: debugee started!"); + log.display("**> isPrivate001a: debugee started!"); isPrivate001a isPrivate001a_obj = new isPrivate001a(); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isPrivate001a: waiting for \"quit\" signal..."); + log.display("**> isPrivate001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isPrivate001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isPrivate001a: completed succesfully!"); + log.display("**> isPrivate001a: \"quit\" signal recieved!"); + log.display("**> isPrivate001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isPrivate001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java index 49780d19b271..fb20a97549b6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java @@ -133,11 +133,7 @@ private int runThis (String argv[], PrintStream out) { Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java index 3f16eb2378bf..9fbeb819257a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java @@ -49,7 +49,6 @@ * nsk.jdi.Accessible.isProtected.isProtected001a * @run driver * nsk.jdi.Accessible.isProtected.isProtected001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java index 361456d2ed52..6f41500ac087 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isProtected001 JDI test. */ public class isProtected001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -82,31 +81,18 @@ protected static class s_interf_impl implements s_interf {} pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isProtected001a: debugee started!"); + log.display("**> isProtected001a: debugee started!"); isProtected001a isProtected001a_obj = new isProtected001a(); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isProtected001a: waiting for \"quit\" signal..."); + log.display("**> isProtected001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isProtected001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isProtected001a: completed succesfully!"); + log.display("**> isProtected001a: \"quit\" signal recieved!"); + log.display("**> isProtected001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isProtected001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java index 0238dc5e6a06..d52ae0f96374 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java @@ -133,11 +133,7 @@ private int runThis (String argv[], PrintStream out) { Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java index 50fe8fd80156..afa48f784633 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java @@ -49,7 +49,6 @@ * nsk.jdi.Accessible.isPublic.isPublic001a * @run driver * nsk.jdi.Accessible.isPublic.isPublic001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java index 65493885ae0d..2d3307508d64 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isPublic001 JDI test. */ public class isPublic001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -81,31 +80,18 @@ protected static class s_interf_impl implements s_interf {} pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isPublic001a: debugee started!"); + log.display("**> isPublic001a: debugee started!"); isPublic001a isPublic001a_obj = new isPublic001a(); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isPublic001a: waiting for \"quit\" signal..."); + log.display("**> isPublic001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isPublic001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isPublic001a: completed succesfully!"); + log.display("**> isPublic001a: \"quit\" signal recieved!"); + log.display("**> isPublic001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isPublic001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java index a8d22483ad87..00dcac2720ea 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java @@ -125,11 +125,7 @@ private int runThis (String argv[], PrintStream out) { Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java index dc00a5d81cfc..08190bf75fcf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java @@ -50,7 +50,6 @@ * nsk.jdi.Accessible.modifiers.modifiers001a * @run driver * nsk.jdi.Accessible.modifiers.modifiers001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java index 19d2081780e9..45422a5ca3a7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the modifiers001 JDI test. */ public class modifiers001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); // Classes must be loaded and linked, so all fields must be // initialized @@ -73,31 +72,18 @@ static class s_interf_impl implements s_interf {} interf_impl m_interf_impl_0 = new interf_impl(); interf m_interf_0, m_interf_1[] = {m_interf_0}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i modifiers001a: debugee started!"); + log.display("**> modifiers001a: debugee started!"); modifiers001a obj = new modifiers001a(); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> modifiers001a: waiting for \"quit\" signal..."); + log.display("**> modifiers001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> modifiers001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> modifiers001a: completed succesfully!"); + log.display("**> modifiers001a: \"quit\" signal recieved!"); + log.display("**> modifiers001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> modifiers001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java index 501f38358d86..cf521bd6dff8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java @@ -128,11 +128,7 @@ private int runThis (String argv[], PrintStream out) { Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java index 7c0dfd0e82bf..02a3adb50bcc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java @@ -53,7 +53,6 @@ * nsk.jdi.ClassObjectReference.reflectedType.reflectype001a * @run driver * nsk.jdi.ClassObjectReference.reflectedType.reflectype001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java index 9bc458b9bb7b..e53fc8248ec6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the reflectype001 JDI test. */ public class reflectype001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -75,33 +73,21 @@ class package_interf_impl implements package_interf {} package_interf_impl pii0 = new package_interf_impl(); package_interf package_interf0, package_interf1[]={package_interf0}, package_interf2[][]={package_interf1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } public static void main (String argv[]) { - for (int i=0; i reflectype001a: debugee started!"); + log.display("**> reflectype001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); reflectype001a reflectype001a_obj = new reflectype001a(); - print_log_on_verbose("**> reflectype001a: waiting for \"quit\" signal..."); + log.display("**> reflectype001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> reflectype001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> reflectype001a: completed succesfully!"); + log.display("**> reflectype001a: \"quit\" signal recieved!"); + log.display("**> reflectype001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> reflectype001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java index efec917716a0..a261fa366511 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ClassObjectReference.reflectedType.reflectype002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java index 0f5cda757519..11cee2ff1fd5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,59 +29,48 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the reflectype002 JDI test. */ public class reflectype002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ClassObjectReference.reflectedType."; private final static String checked_class_name = package_prefix + "reflectype002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> reflectype002a: debugee started!"); + log.display("**> reflectype002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; - print_log_on_verbose("**> reflectype002a: waiting for \"checked class dir\" info..."); + log.display("**> reflectype002a: waiting for \"checked class dir\" info..."); ClassUnloader classUnloader = new ClassUnloader(); try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> reflectype002a: checked class loaded:" + checked_class_name); + log.display("--> reflectype002a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> reflectype002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> reflectype002a: checked class NOT loaded:" + checked_class_name); + log.display("--> reflectype002a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> reflectype002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> reflectype002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> reflectype002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> reflectype002a: completed!"); + log.display("**> reflectype002a: \"quit\" signal recieved!"); + log.display("**> reflectype002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -91,24 +80,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> reflectype002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> reflectype002a: enforce to unload checked class..."); + log.display("**> reflectype002a: \"continue\" signal recieved!"); + log.display("**> reflectype002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> reflectype002a: checked class may be NOT unloaded!"); + log.display("**> reflectype002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> reflectype002a: checked class unloaded!"); + log.display("**> reflectype002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> reflectype002a: waiting for \"quit\" signal..."); + log.display("**> reflectype002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> reflectype002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> reflectype002a: completed!"); + log.display("**> reflectype002a: \"quit\" signal recieved!"); + log.display("**> reflectype002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> reflectype002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java index fe0c781b56f8..b6d4d052ed31 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.allFields.allfields001a * @run driver * nsk.jdi.ReferenceType.allFields.allfields001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java index 8fa0790cc716..b07bb2f291cc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allfields001 JDI test. */ public class allfields001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i allfields001a: debugee started!"); + log.display("**> allfields001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); allfields001aClassForCheck class_for_check = new allfields001aClassForCheck(); - print_log_on_verbose("**> allfields001a: waiting for \"quit\" signal..."); + log.display("**> allfields001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allfields001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allfields001a: completed succesfully!"); + log.display("**> allfields001a: \"quit\" signal recieved!"); + log.display("**> allfields001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allfields001a: unexpected signal (no \"quit\") - " + instruction); @@ -158,5 +142,4 @@ interface allfields001aInterfaceForCheck { static final long ambiguous_prim_field = 1; static final Object ambiguous_ref_field = new Object(); - } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java index ee94fd88bc42..53175b0e6edb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java @@ -100,11 +100,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/allFields/allfields002 test LOG:"); print_log_on_verbose("==> test checks allFields() method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java index feb95cf9a76a..0e4ef769249b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.allFields.allfields002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java index eb4e99cd953b..5d0030cde684 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,35 +28,20 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the allfields002 JDI test. */ public class allfields002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.allFields."; private final static String checked_class_name = package_prefix + "allfields002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i allfields002a: debugee started!"); + log.display("**> allfields002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,19 +50,17 @@ public static void main (String argv[]) { allfields002aClassLoader customClassLoader = new allfields002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> allfields002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> allfields002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> allfields002a: checked class NOT loaded: " + e); + log.display("--> allfields002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> allfields002a: waiting for \"quit\" signal..."); + log.display("**> allfields002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allfields002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allfields002a: completed succesfully!"); + log.display("**> allfields002a: \"quit\" signal recieved!"); + log.display("**> allfields002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allfields002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java index 053a6ff34c52..904e0ff4e3ef 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.allFields.allfields003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java index 68b88e0af6c3..0cdd206d069a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,63 +29,49 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allfields003 JDI test. */ public class allfields003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - + private static Log log = new Log(System.err); static String package_prefix = "nsk.jdi.ReferenceType.allFields."; static String checked_class_name = package_prefix + "allfields003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> allfields003a: debugee started!"); + log.display("**> allfields003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> allfields003a: waiting for \"checked class dir\" info..."); + log.display("**> allfields003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; - print_log_on_verbose - ("--> allfields003a: checked class dir:" + checked_class_dir); + log.display("--> allfields003a: checked class dir:" + checked_class_dir); ClassUnloader classUnloader = new ClassUnloader(); try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> allfields003a: checked class loaded:" + checked_class_name); + log.display("--> allfields003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException - print_log_on_verbose - ("**> allfields003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> allfields003a: checked class NOT loaded:" + checked_class_name); + log.display("**> allfields003a: load class: exception thrown = " + e.toString()); + log.display("--> allfields003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> allfields003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> allfields003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allfields003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allfields003a: completed!"); + log.display("**> allfields003a: \"quit\" signal recieved!"); + log.display("**> allfields003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -95,24 +81,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> allfields003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> allfields003a: enforce to unload checked class..."); + log.display("**> allfields003a: \"continue\" signal recieved!"); + log.display("**> allfields003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> allfields003a: checked class may be NOT unloaded!"); + log.display("**> allfields003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> allfields003a: checked class unloaded!"); + log.display("**> allfields003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> allfields003a: waiting for \"quit\" signal..."); + log.display("**> allfields003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allfields003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allfields003a: completed!"); + log.display("**> allfields003a: \"quit\" signal recieved!"); + log.display("**> allfields003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allfields003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java index d21c2c2aa06c..6415b2eb96e8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.allFields.allfields004a * @run driver * nsk.jdi.ReferenceType.allFields.allfields004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java index 2384484e59ca..9c72ed26c713 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allfields004 JDI test. */ public class allfields004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i allfields004a: debugee started!"); + log.display("**> allfields004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); allfields004aClassForCheck class_for_check = new allfields004aClassForCheck(); - print_log_on_verbose("**> allfields004a: waiting for \"quit\" signal..."); + log.display("**> allfields004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allfields004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allfields004a: completed succesfully!"); + log.display("**> allfields004a: \"quit\" signal recieved!"); + log.display("**> allfields004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> allfields004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java index b5b0ab74d9ee..9cadf25e457e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.allMethods.allmethods001a * @run driver * nsk.jdi.ReferenceType.allMethods.allmethods001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java index 963609fa7df6..16eaeceb46a0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allmethods001 JDI test. */ public class allmethods001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.allMethods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "allmethods001aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i allmethods001a: debugee started!"); + log.display("**> allmethods001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, allmethods001a.class.getClassLoader()); - print_log_on_verbose - ("--> allmethods001a: checked class loaded:" + checked_class_name); + log.display("--> allmethods001a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> allmethods001a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> allmethods001a: checked class NOT loaded: " + checked_class_name); + log.display("--> allmethods001a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> allmethods001a: waiting for \"quit\" signal..."); + log.display("**> allmethods001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allmethods001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allmethods001a: completed succesfully!"); + log.display("**> allmethods001a: \"quit\" signal recieved!"); + log.display("**> allmethods001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allmethods001a: unexpected signal (no \"quit\") - " + instruction); @@ -196,7 +179,6 @@ public void i_interf_overridden_void_par_method(int i) {} // static initializer static {} - } abstract class allmethods001aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java index 856366d67e0d..cbf1382e43a2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java @@ -103,11 +103,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/allMethods/allmethods002 test LOG:"); print_log_on_verbose("==> test checks allMethods() method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java index f5478f4c0e3c..3b79856a33d0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.allMethods.allmethods002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java index 0ea324a2aa54..10c9e7205061 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the allmethods002 JDI test. */ public class allmethods002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.allMethods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "allmethods002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i allmethods002a: debugee started!"); + log.display("**> allmethods002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { allmethods002aClassLoader customClassLoader = new allmethods002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> allmethods002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> allmethods002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> allmethods002a: checked class NOT loaded: " + e); + log.display("--> allmethods002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> allmethods002a: waiting for \"quit\" signal..."); + log.display("**> allmethods002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allmethods002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allmethods002a: completed succesfully!"); + log.display("**> allmethods002a: \"quit\" signal recieved!"); + log.display("**> allmethods002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allmethods002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java index a0e8bd2b7f15..dddea049634a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.allMethods.allmethods003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java index f8a7af6b7177..211c980ecb0b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allmethods003 JDI test. */ public class allmethods003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); static String package_prefix = "nsk.jdi.ReferenceType.allMethods."; static String checked_class_name = package_prefix + "allmethods003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> allmethods003a: debugee started!"); + log.display("**> allmethods003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> allmethods003a: waiting for \"checked class dir\" info..."); + log.display("**> allmethods003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -65,23 +56,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> allmethods003a: checked class loaded:" + checked_class_name); + log.display("--> allmethods003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> allmethods003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> allmethods003a: checked class NOT loaded:" + checked_class_name); + log.display("--> allmethods003a: checked class NOT loaded:" + checked_class_name); // Debugger finds this fact itself } - print_log_on_verbose("**> allmethods003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> allmethods003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allmethods003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allmethods003a: completed!"); + log.display("**> allmethods003a: \"quit\" signal recieved!"); + log.display("**> allmethods003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -91,24 +80,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> allmethods003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> allmethods003a: enforce to unload checked class..."); + log.display("**> allmethods003a: \"continue\" signal recieved!"); + log.display("**> allmethods003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> allmethods003a: checked class may be NOT unloaded!"); + log.display("**> allmethods003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> allmethods003a: checked class unloaded!"); + log.display("**> allmethods003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> allmethods003a: waiting for \"quit\" signal..."); + log.display("**> allmethods003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allmethods003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allmethods003a: completed!"); + log.display("**> allmethods003a: \"quit\" signal recieved!"); + log.display("**> allmethods003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> allmethods003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java index f6981d4a6e91..db60ddd2eee7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java @@ -45,7 +45,6 @@ * nsk.jdi.ReferenceType.allMethods.allmethods004a * @run driver * nsk.jdi.ReferenceType.allMethods.allmethods004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java index c7d94273b10d..bf4da3b2d028 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the allmethods004 JDI test. */ public class allmethods004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i allmethods004a: debugee started!"); + log.display("**> allmethods004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); allmethods004aClassForCheck class_for_check = new allmethods004aClassForCheck(); - print_log_on_verbose("**> allmethods004a: waiting for \"quit\" signal..."); + log.display("**> allmethods004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> allmethods004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> allmethods004a: completed succesfully!"); + log.display("**> allmethods004a: \"quit\" signal recieved!"); + log.display("**> allmethods004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> allmethods004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java index 7da86a967382..7f5c8bdbe4a5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java @@ -44,7 +44,6 @@ * nsk.jdi.ReferenceType.classObject.classobj001a * @run driver * nsk.jdi.ReferenceType.classObject.classobj001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java index 8c9f3d6d05e5..84d1cf4e63cc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the classobj001 JDI test. */ public class classobj001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -75,33 +73,20 @@ static class s_interf_impl implements s_interf {} package_interf package_interf0, package_interf1[]={package_interf0}, package_interf2[][]={package_interf1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i classobj001a: debugee started!"); + log.display("**> classobj001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); classobj001a classobj001a_obj = new classobj001a(); - print_log_on_verbose("**> classobj001a: waiting for \"quit\" signal..."); + log.display("**> classobj001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> classobj001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> classobj001a: completed succesfully!"); + log.display("**> classobj001a: \"quit\" signal recieved!"); + log.display("**> classobj001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> classobj001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java index ab751a1f29c3..08376ce6d6fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.classObject.classobj002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java index 2d9b1bce94d2..c54522ee97bf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the classobj002 JDI test. */ public class classobj002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.classObject."; private final static String checked_class_name = package_prefix + "classobj002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> classobj002a: debugee started!"); + log.display("**> classobj002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> classobj002a: waiting for \"checked class dir\" info..."); + log.display("**> classobj002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -65,23 +56,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> classobj002a: checked class loaded:" + checked_class_name); + log.display("--> classobj002a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> classobj002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> classobj002a: checked class NOT loaded:" + checked_class_name); + log.display("--> classobj002a: checked class NOT loaded:" + checked_class_name); // Debugger finds this fact itself } - print_log_on_verbose("**> classobj002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> classobj002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> classobj002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> classobj002a: completed!"); + log.display("**> classobj002a: \"quit\" signal recieved!"); + log.display("**> classobj002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -91,24 +80,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> classobj002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> classobj002a: enforce to unload checked class..."); + log.display("**> classobj002a: \"continue\" signal recieved!"); + log.display("**> classobj002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> classobj002a: checked class may be NOT unloaded!"); + log.display("**> classobj002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> classobj002a: checked class unloaded!"); + log.display("**> classobj002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> classobj002a: waiting for \"quit\" signal..."); + log.display("**> classobj002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> classobj002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> classobj002a: completed!"); + log.display("**> classobj002a: \"quit\" signal recieved!"); + log.display("**> classobj002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> classobj002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java index 1b1aff020cb1..fc8de81a532c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java @@ -50,7 +50,6 @@ * nsk.jdi.ReferenceType.equals.equals001a * @run driver * nsk.jdi.ReferenceType.equals.equals001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java index 75551cc35466..7d3c5bfd9a37 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,16 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the equals001 JDI test. */ public class equals001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -77,33 +74,20 @@ static class s_interf_impl implements s_interf {} interf_for_check1[]={interf_for_check0}, interf_for_check2[][]={interf_for_check1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i equals001a: debugee started!"); + log.display("**> equals001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); equals001a equals001a_obj = new equals001a(); - print_log_on_verbose("**> equals001a: waiting for \"quit\" signal..."); + log.display("**> equals001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> equals001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> equals001a: completed succesfully!"); + log.display("**> equals001a: \"quit\" signal recieved!"); + log.display("**> equals001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> equals001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java index e1c25e9dbdd4..986d130214d2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.equals.equals002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java index 0fc1f3a28182..292934aae9e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the equals002 JDI test. */ public class equals002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.equals."; private final static String checked_class_name = package_prefix + "equals002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> equals002a: debugee started!"); + log.display("**> equals002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> equals002a: waiting for \"checked class dir\" info..."); + log.display("**> equals002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> equals002a: checked class loaded:" + checked_class_name); + log.display("--> equals002a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> equals002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> equals002a: checked class NOT loaded:" + checked_class_name); + log.display("--> equals002a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> equals002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> equals002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> equals002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> equals002a: completed!"); + log.display("**> equals002a: \"quit\" signal recieved!"); + log.display("**> equals002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> equals002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> equals002a: enforce to unload checked class..."); + log.display("**> equals002a: \"continue\" signal recieved!"); + log.display("**> equals002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> equals002a: checked class may be NOT unloaded!"); + log.display("**> equals002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> equals002a: checked class unloaded!"); + log.display("**> equals002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> equals002a: waiting for \"quit\" signal..."); + log.display("**> equals002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> equals002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> equals002a: completed!"); + log.display("**> equals002a: \"quit\" signal recieved!"); + log.display("**> equals002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> equals002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java index a1d0665a88b8..08cbf8c05c05 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java @@ -43,7 +43,6 @@ * nsk.jdi.ReferenceType.failedToInitialize.failedToInitialize001a * @run driver * nsk.jdi.ReferenceType.failedToInitialize.failedToInitialize001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java index f8c801e881c6..bebc8fb84c62 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the failedToInitialize001 JDI test. */ public class failedToInitialize001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); failedToInitialize001 a001_0=new failedToInitialize001(); @@ -43,22 +42,9 @@ public class failedToInitialize001a { interf_impl interf_impl_0 = new interf_impl(); interf interf_0, interf_1[]={interf_0}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i failedToInitialize001a: debugee started!"); + log.display("**> failedToInitialize001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -71,8 +57,7 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } catch (ExceptionInInitializerError e) { - print_log_on_verbose - ("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_class)!"); + log.display("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_class)!"); } try { @@ -83,16 +68,15 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } catch (ExceptionInInitializerError e) { - print_log_on_verbose - ("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_subcl)!"); + log.display("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_subcl)!"); } - print_log_on_verbose("**> failedToInitialize001a: waiting for \"quit\" signal..."); + log.display("**> failedToInitialize001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> failedToInitialize001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> failedToInitialize001a: completed succesfully!"); + log.display("**> failedToInitialize001a: \"quit\" signal recieved!"); + log.display("**> failedToInitialize001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> failedToInitialize001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java index 703bb6c54aa8..701b4b183c00 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.failedToInitialize.failedtoinit002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java index cbd88e242365..6a8e678f2236 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the failedtoinit002 JDI test. */ public class failedtoinit002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.failedToInitialize."; private final static String checked_class_name = package_prefix + "failedtoinit002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> failedtoinit002a: debugee started!"); + log.display("**> failedtoinit002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> failedtoinit002a: waiting for \"checked class dir\" info..."); + log.display("**> failedtoinit002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> failedtoinit002a: checked class loaded: " + checked_class_name); + log.display("--> failedtoinit002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> failedtoinit002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> failedtoinit002a: checked class NOT loaded: " + checked_class_name); + log.display("--> failedtoinit002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> failedtoinit002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> failedtoinit002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> failedtoinit002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> failedtoinit002a: completed!"); + log.display("**> failedtoinit002a: \"quit\" signal recieved!"); + log.display("**> failedtoinit002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> failedtoinit002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> failedtoinit002a: enforce to unload checked class..."); + log.display("**> failedtoinit002a: \"continue\" signal recieved!"); + log.display("**> failedtoinit002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> failedtoinit002a: checked class may be NOT unloaded!"); + log.display("**> failedtoinit002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> failedtoinit002a: checked class unloaded!"); + log.display("**> failedtoinit002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> failedtoinit002a: waiting for \"quit\" signal..."); + log.display("**> failedtoinit002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> failedtoinit002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> failedtoinit002a: completed!"); + log.display("**> failedtoinit002a: \"quit\" signal recieved!"); + log.display("**> failedtoinit002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> failedtoinit002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java index a3fdea994f11..9248927ef618 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java @@ -50,7 +50,6 @@ * nsk.jdi.ReferenceType.fieldByName.fieldbyname001a * @run driver * nsk.jdi.ReferenceType.fieldByName.fieldbyname001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java index a08cb86538ab..fa24fc7b8657 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the fieldbyname001 JDI test. */ public class fieldbyname001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i fieldbyname001a: debugee started!"); + log.display("**> fieldbyname001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); fieldbyname001aClassForCheck class_for_check = new fieldbyname001aClassForCheck(); - print_log_on_verbose("**> fieldbyname001a: waiting for \"quit\" signal..."); + log.display("**> fieldbyname001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fieldbyname001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fieldbyname001a: completed succesfully!"); + log.display("**> fieldbyname001a: \"quit\" signal recieved!"); + log.display("**> fieldbyname001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fieldbyname001a: unexpected signal (no \"quit\") - " + instruction); @@ -158,5 +142,4 @@ interface fieldbyname001aInterfaceForCheck { static final long ambiguous_prim_field = 1; static final Object ambiguous_ref_field = new Object(); - } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java index 7721afec2a2a..6623f9eeea47 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java @@ -103,11 +103,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/fieldByName/fieldbyname002 test LOG:"); print_log_on_verbose("==> test checks fieldByName(...) method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java index f945b8d74de0..83f0e9a92c24 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.fieldByName.fieldbyname002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java index 84d51fc58f2d..40554b2e53c6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the fieldbyname002 JDI test. */ public class fieldbyname002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.fieldByName."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "fieldbyname002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i fieldbyname002a: debugee started!"); + log.display("**> fieldbyname002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { fieldbyname002aClassLoader customClassLoader = new fieldbyname002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> fieldbyname002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> fieldbyname002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> fieldbyname002a: checked class NOT loaded: " + e); + log.display("--> fieldbyname002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> fieldbyname002a: waiting for \"quit\" signal..."); + log.display("**> fieldbyname002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fieldbyname002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fieldbyname002a: completed succesfully!"); + log.display("**> fieldbyname002a: \"quit\" signal recieved!"); + log.display("**> fieldbyname002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fieldbyname002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java index fa5104cad552..b539d5528f07 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.fieldByName.fieldbyname003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java index 8d2cb87f239b..a2ccc80a72a7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the fieldbyname003 JDI test. */ public class fieldbyname003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); static String package_prefix = "nsk.jdi.ReferenceType.fieldByName."; static String checked_class_name = package_prefix + "fieldbyname003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> fieldbyname003a: debugee started!"); + log.display("**> fieldbyname003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> fieldbyname003a: waiting for \"checked class dir\" info..."); + log.display("**> fieldbyname003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -65,23 +56,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> fieldbyname003a: checked class loaded:" + checked_class_name); + log.display("--> fieldbyname003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> fieldbyname003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> fieldbyname003a: checked class NOT loaded:" + checked_class_name); + log.display("--> fieldbyname003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> fieldbyname003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> fieldbyname003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fieldbyname003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fieldbyname003a: completed!"); + log.display("**> fieldbyname003a: \"quit\" signal recieved!"); + log.display("**> fieldbyname003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -91,24 +80,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> fieldbyname003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> fieldbyname003a: enforce to unload checked class..."); + log.display("**> fieldbyname003a: \"continue\" signal recieved!"); + log.display("**> fieldbyname003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> fieldbyname003a: checked class may be NOT unloaded!"); + log.display("**> fieldbyname003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> fieldbyname003a: checked class unloaded!"); + log.display("**> fieldbyname003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> fieldbyname003a: waiting for \"quit\" signal..."); + log.display("**> fieldbyname003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fieldbyname003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fieldbyname003a: completed!"); + log.display("**> fieldbyname003a: \"quit\" signal recieved!"); + log.display("**> fieldbyname003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fieldbyname003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java index 45a46baa6f87..14489fd9ce7c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.fields.fields001a * @run driver * nsk.jdi.ReferenceType.fields.fields001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java index d72fb7c51249..6c0d4e2ca2e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the fields001 JDI test. */ public class fields001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i fields001a: debugee started!"); + log.display("**> fields001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); fields001aClassForCheck class_for_check = new fields001aClassForCheck(); - print_log_on_verbose("**> fields001a: waiting for \"quit\" signal..."); + log.display("**> fields001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fields001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fields001a: completed succesfully!"); + log.display("**> fields001a: \"quit\" signal recieved!"); + log.display("**> fields001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fields001a: unexpected signal (no \"quit\") - " + instruction); @@ -158,5 +142,4 @@ interface fields001aInterfaceForCheck { static final long ambiguous_prim_field = 1; static final Object ambiguous_ref_field = new Object(); - } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java index 3c55e8036359..fd064d1bbe62 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,6 @@ public class fields002 { static ArgumentHandler argsHandler; static Log test_log_handler; - static boolean verbose_mode = false; // test argument -verbose switches to true - // - for more easy failure evaluation /** The main class names of the debugger & debugee applications. */ private final static String @@ -55,7 +53,6 @@ public class fields002 { private final static String classLoaderName = package_prefix + "fields002aClassLoader"; private final static String classFieldName = "loadedClass"; - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -72,22 +69,14 @@ public static int run (String argv[], PrintStream out) { int v_test_result = new fields002().runThis(argv,out); if ( v_test_result == 2/*STATUS_FAILED*/ ) { - print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields002 test FAILED"); + test_log_handler.complain("\n==> nsk/jdi/ReferenceType/fields/fields002 test FAILED"); } else { - print_log_on_verbose("\n==> nsk/jdi/ReferenceType/fields/fields002 test PASSED"); + test_log_handler.display("\n==> nsk/jdi/ReferenceType/fields/fields002 test PASSED"); } return v_test_result; } - private static void print_log_on_verbose(String message) { - test_log_handler.display(message); - } - - private static void print_log_anyway(String message) { - test_log_handler.complain(message); - } - /** * Non-static variant of the method run(args,out) */ @@ -97,40 +86,33 @@ private int runThis (String argv[], PrintStream out) { test_log_handler = new Log(out, argsHandler); Binder binder = new Binder(argsHandler, test_log_handler); - print_log_on_verbose("==> nsk/jdi/ReferenceType/fields/fields002 test LOG:"); - print_log_on_verbose("==> test checks fields() method of ReferenceType interface "); - print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + test_log_handler.display("==> nsk/jdi/ReferenceType/fields/fields002 test LOG:"); + test_log_handler.display("==> test checks fields() method of ReferenceType interface "); + test_log_handler.display(" of the com.sun.jdi package for not prepared class\n"); String debugee_launch_command = debugeeName; - if (verbose_mode) { - debugee_launch_command = debugeeName + " -vbs"; - } Debugee debugee = binder.bindToDebugee(debugee_launch_command); IOPipe pipe = new IOPipe(debugee); - debugee.redirectStderr(out); - print_log_on_verbose("--> fields002: fields002a debugee launched"); + test_log_handler.display("--> fields002: fields002a debugee launched"); debugee.resume(); String line = pipe.readln(); if (line == null) { - print_log_anyway - ("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + test_log_handler.complain("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); return 2/*STATUS_FAILED*/; } if (!line.equals("ready")) { - print_log_anyway - ("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + test_log_handler.complain("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); return 2/*STATUS_FAILED*/; } else { - print_log_on_verbose("--> fields002: debugee's \"ready\" signal recieved!"); + test_log_handler.display("--> fields002: debugee's \"ready\" signal recieved!"); } - print_log_on_verbose - ("--> fields002: check ReferenceType.fields() method for not prepared " + test_log_handler.display("--> fields002: check ReferenceType.fields() method for not prepared " + class_for_check + " class..."); boolean class_not_found_error = false; boolean fields_method_error = false; @@ -138,7 +120,7 @@ private int runThis (String argv[], PrintStream out) { while ( true ) { // test body ReferenceType loaderRefType = debugee.classByName(classLoaderName); if (loaderRefType == null) { - print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + test_log_handler.complain("##> Could NOT FIND custom class loader: " + classLoaderName); class_not_found_error = true; break; } @@ -150,7 +132,7 @@ private int runThis (String argv[], PrintStream out) { try { classObjRef = (ClassObjectReference)classValue; } catch (Exception e) { - print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + test_log_handler.complain("##> Unexpected exception while getting ClassObjectReference : " + e); class_not_found_error = true; break; } @@ -158,34 +140,27 @@ private int runThis (String argv[], PrintStream out) { ReferenceType refType = classObjRef.reflectedType(); boolean isPrep = refType.isPrepared(); if (isPrep) { - print_log_anyway - ("##> fields002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + test_log_handler.complain("##> fields002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); class_not_found_error = true; break; } else { - print_log_on_verbose - ("--> fields002: isPrepared() returns for " + class_for_check + " : " + isPrep); + test_log_handler.display("--> fields002: isPrepared() returns for " + class_for_check + " : " + isPrep); } List fields_list = null; try { fields_list = refType.fields(); - print_log_anyway - ("##> fields002: FAILED: NO any Exception thrown!"); - print_log_anyway - ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + test_log_handler.complain("##> fields002: FAILED: NO any Exception thrown!"); + test_log_handler.complain("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); fields_method_error = true; } catch (Exception expt) { if (expt instanceof com.sun.jdi.ClassNotPreparedException) { - print_log_on_verbose - ("--> fields002: PASSED: expected Exception thrown - " + expt.toString()); + test_log_handler.display("--> fields002: PASSED: expected Exception thrown - " + expt.toString()); } else { - print_log_anyway - ("##> fields002: FAILED: unexpected Exception thrown - " + expt.toString()); - print_log_anyway - ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + test_log_handler.complain("##> fields002: FAILED: unexpected Exception thrown - " + expt.toString()); + test_log_handler.complain("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); fields_method_error = true; } } @@ -196,19 +171,17 @@ private int runThis (String argv[], PrintStream out) { v_test_result = 2/*STATUS_FAILED*/; } - print_log_on_verbose("--> fields002: waiting for debugee finish..."); + test_log_handler.display("--> fields002: waiting for debugee finish..."); pipe.println("quit"); debugee.waitFor(); int status = debugee.getStatus(); if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { - print_log_anyway - ("##> fields002: UNEXPECTED Debugee's exit status (not 95) - " + status); + test_log_handler.complain("##> fields002: UNEXPECTED Debugee's exit status (not 95) - " + status); v_test_result = 2/*STATUS_FAILED*/; } else { - print_log_on_verbose - ("--> fields002: expected Debugee's exit status - " + status); + test_log_handler.display("--> fields002: expected Debugee's exit status - " + status); } return v_test_result; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java index 5bd713a13649..aff66a05f620 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.fields.fields002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java index 5f0501c794e8..0b76dd34241f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the fields002 JDI test. */ public class fields002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.fields."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "fields002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i fields002a: debugee started!"); + log.display("**> fields002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { fields002aClassLoader customClassLoader = new fields002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> fields002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> fields002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> fields002a: checked class NOT loaded: " + e); + log.display("--> fields002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> fields002a: waiting for \"quit\" signal..."); + log.display("**> fields002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fields002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fields002a: completed succesfully!"); + log.display("**> fields002a: \"quit\" signal recieved!"); + log.display("**> fields002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fields002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java index ab6af3a98e15..1ec4980a2cab 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.fields.fields003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java index f808a0577992..cb710ab4ef8b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the fields003 JDI test. */ public class fields003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private static final String package_prefix = "nsk.jdi.ReferenceType.fields."; private static final String checked_class_name = package_prefix + "fields003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> fields003a: debugee started!"); + log.display("**> fields003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> fields003a: waiting for \"checked class dir\" info..."); + log.display("**> fields003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> fields003a: checked class loaded:" + checked_class_name); + log.display("--> fields003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> fields003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> fields003a: checked class NOT loaded:" + checked_class_name); + log.display("--> fields003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> fields003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> fields003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fields003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fields003a: completed!"); + log.display("**> fields003a: \"quit\" signal recieved!"); + log.display("**> fields003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> fields003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> fields003a: enforce to unload checked class..."); + log.display("**> fields003a: \"continue\" signal recieved!"); + log.display("**> fields003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> fields003a: checked class may be NOT unloaded!"); + log.display("**> fields003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> fields003a: checked class unloaded!"); + log.display("**> fields003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> fields003a: waiting for \"quit\" signal..."); + log.display("**> fields003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fields003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fields003a: completed!"); + log.display("**> fields003a: \"quit\" signal recieved!"); + log.display("**> fields003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> fields003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java index 7eb5fbd7e38e..492954757b3a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.fields.fields004a * @run driver * nsk.jdi.ReferenceType.fields.fields004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java index 9dc8565cfe41..b8c971b87760 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the fields004 JDI test. */ public class fields004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i fields004a: debugee started!"); + log.display("**> fields004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); fields004aClassForCheck class_for_check = new fields004aClassForCheck(); - print_log_on_verbose("**> fields004a: waiting for \"quit\" signal..."); + log.display("**> fields004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> fields004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> fields004a: completed succesfully!"); + log.display("**> fields004a: \"quit\" signal recieved!"); + log.display("**> fields004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> fields004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java index 51a6f77a27db..606814297a9d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.hashCode.hashcode001a * @run driver * nsk.jdi.ReferenceType.hashCode.hashcode001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java index 723035860f7f..7021b1674155 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,16 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the hashcode001 JDI test. */ public class hashcode001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -75,33 +72,20 @@ static class s_interf_impl implements s_interf {} InterfaceForCheck_impl interf_for_check_impl0 = new InterfaceForCheck_impl(); InterfaceForCheck interf_for_check0,interf_for_check1[]={interf_for_check0}, interf_for_check2[][]={interf_for_check1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i hashcode001a: debugee started!"); + log.display("**> hashcode001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); hashcode001a hashcode001a_obj = new hashcode001a(); - print_log_on_verbose("**> hashcode001a: waiting for \"quit\" signal..."); + log.display("**> hashcode001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> hashcode001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> hashcode001a: completed succesfully!"); + log.display("**> hashcode001a: \"quit\" signal recieved!"); + log.display("**> hashcode001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> hashcode001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java index 693171c9dfe1..e414117c3ba7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.hashCode.hashcode002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java index f72a629b8a87..bd290d3e0e38 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the hashcode002 JDI test. */ public class hashcode002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.hashCode."; private final static String checked_class_name = package_prefix + "hashcode002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> hashcode002a: debugee started!"); + log.display("**> hashcode002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> hashcode002a: waiting for \"checked class dir\" info..."); + log.display("**> hashcode002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> hashcode002a: checked class loaded: " + checked_class_name); + log.display("--> hashcode002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> hashcode002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> hashcode002a: checked class NOT loaded: " + checked_class_name); + log.display("--> hashcode002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> hashcode002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> hashcode002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> hashcode002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> hashcode002a: completed!"); + log.display("**> hashcode002a: \"quit\" signal recieved!"); + log.display("**> hashcode002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> hashcode002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> hashcode002a: enforce to unload checked class..."); + log.display("**> hashcode002a: \"continue\" signal recieved!"); + log.display("**> hashcode002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> hashcode002a: checked class may be NOT unloaded!"); + log.display("**> hashcode002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> hashcode002a: checked class unloaded!"); + log.display("**> hashcode002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> hashcode002a: waiting for \"quit\" signal..."); + log.display("**> hashcode002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> hashcode002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> hashcode002a: completed!"); + log.display("**> hashcode002a: \"quit\" signal recieved!"); + log.display("**> hashcode002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> hashcode002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java index 2bd3e7615d11..1492064dfe6a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java @@ -43,7 +43,6 @@ * nsk.jdi.ReferenceType.isAbstract.isAbstract001a * @run driver * nsk.jdi.ReferenceType.isAbstract.isAbstract001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java index 464162b9edba..c8897cdadc49 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isAbstract001 JDI test. */ public class isAbstract001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); // Abstract classes must be extended by a class and that class must be // initialized, so that abstract classes could be returnedin debugger @@ -61,31 +60,18 @@ static class s_interf_impl implements s_interf {} abstr_interf abstr_interf_0, abstr_interf_1[]={abstr_interf_0}; abstr_interf_impl abstr_interf_impl_0= new abstr_interf_impl(); - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isAbstract001a: debugee started!"); + log.display("**> isAbstract001a: debugee started!"); isAbstract001a isAbstract001a_obj = new isAbstract001a(); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isAbstract001a: waiting for \"quit\" signal..."); + log.display("**> isAbstract001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isAbstract001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isAbstract001a: completed succesfully!"); + log.display("**> isAbstract001a: \"quit\" signal recieved!"); + log.display("**> isAbstract001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isAbstract001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java index b61c14d3d4b0..5e030c62b952 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.isAbstract.isabstract002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java index af85baf3d4d7..bb0702047e8b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isabstract002 JDI test. */ public class isabstract002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.isAbstract."; static String checked_class_name = package_prefix + "isabstract002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> isabstract002a: debugee started!"); + log.display("**> isabstract002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isabstract002a: waiting for \"checked class dir\" info..."); + log.display("**> isabstract002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> isabstract002a: checked class loaded: " + checked_class_name); + log.display("--> isabstract002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> isabstract002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> isabstract002a: checked class NOT loaded: " + checked_class_name); + log.display("--> isabstract002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> isabstract002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> isabstract002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isabstract002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isabstract002a: completed!"); + log.display("**> isabstract002a: \"quit\" signal recieved!"); + log.display("**> isabstract002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> isabstract002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> isabstract002a: enforce to unload checked class..."); + log.display("**> isabstract002a: \"continue\" signal recieved!"); + log.display("**> isabstract002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> isabstract002a: checked class may be NOT unloaded!"); + log.display("**> isabstract002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> isabstract002a: checked class unloaded!"); + log.display("**> isabstract002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> isabstract002a: waiting for \"quit\" signal..."); + log.display("**> isabstract002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isabstract002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isabstract002a: completed!"); + log.display("**> isabstract002a: \"quit\" signal recieved!"); + log.display("**> isabstract002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isabstract002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java index 2046927d21ca..163479948b3b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java @@ -64,7 +64,6 @@ public class isinit001 { }; - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -111,14 +110,10 @@ private int runThis (String argv[], PrintStream out) { print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); String debugee_launch_command = debugeeName; - if (verbose_mode) { - debugee_launch_command = debugeeName + " -vbs"; - } Debugee debugee = binder.bindToDebugee(debugee_launch_command); IOPipe pipe = new IOPipe(debugee); - debugee.redirectStderr(out); print_log_on_verbose("--> isinit001: isinit001a debugee launched"); debugee.resume(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java index b19a10c05b0d..7cc984c13002 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java @@ -54,7 +54,6 @@ * nsk.jdi.ReferenceType.isInitialized.isinit001a * @run driver * nsk.jdi.ReferenceType.isInitialized.isinit001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java index 91b035ccc293..a4350139b90f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isinit001 JDI test. */ public class isinit001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); NotInitializedClass not_initialized_class_0, not_initialized_class_1[] = {not_initialized_class_0}; @@ -47,33 +45,20 @@ public class isinit001a { int copy_super_class_int_var = SubClass.super_class_int_var; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isinit001a: debugee started!"); + log.display("**> isinit001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); isinit001a isinit001a_obj = new isinit001a(); - print_log_on_verbose("**> isinit001a: waiting for \"quit\" signal..."); + log.display("**> isinit001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isinit001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isinit001a: completed succesfully!"); + log.display("**> isinit001a: \"quit\" signal recieved!"); + log.display("**> isinit001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isinit001a: unexpected signal (no \"quit\") - " + instruction); @@ -88,7 +73,6 @@ class NotInitializedClass {} // not initialized interface interface NotInitializedInterface {} - // initialized interface interface InitializedInterface { static final int int_var = 1; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java index c2b1eac7c1ec..869b47a0eebb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.isInitialized.isinit002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java index 80a766dc2ce1..b96af71248f3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isinit002 JDI test. */ public class isinit002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.isInitialized."; private final static String checked_class_name = package_prefix + "isinit002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> isinit002a: debugee started!"); + log.display("**> isinit002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isinit002a: waiting for \"checked class dir\" info..."); + log.display("**> isinit002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,20 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> isinit002a: checked class loaded: " + checked_class_name); + log.display("--> isinit002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException - print_log_on_verbose - ("**> isinit002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> isinit002a: checked class NOT loaded: " + checked_class_name); + log.display("**> isinit002a: load class: exception thrown = " + e.toString()); + log.display("--> isinit002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> isinit002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> isinit002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isinit002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isinit002a: completed!"); + log.display("**> isinit002a: \"quit\" signal recieved!"); + log.display("**> isinit002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +78,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> isinit002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> isinit002a: enforce to unload checked class..."); + log.display("**> isinit002a: \"continue\" signal recieved!"); + log.display("**> isinit002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> isinit002a: checked class may be NOT unloaded!"); + log.display("**> isinit002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> isinit002a: checked class unloaded!"); + log.display("**> isinit002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> isinit002a: waiting for \"quit\" signal..."); + log.display("**> isinit002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isinit002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isinit002a: completed!"); + log.display("**> isinit002a: \"quit\" signal recieved!"); + log.display("**> isinit002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isinit002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java index 5b98a1ee949d..d7e22d3674f1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java @@ -63,7 +63,6 @@ public class isprepared001 { }; - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -110,9 +109,6 @@ private int runThis (String argv[], PrintStream out) { print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); String debugee_launch_command = debugeeName; - if (verbose_mode) { - debugee_launch_command = debugeeName + " -vbs"; - } Debugee debugee = binder.bindToDebugee(debugee_launch_command); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java index 343b9b1ae24a..853c68bf9d0d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java @@ -54,7 +54,6 @@ * nsk.jdi.ReferenceType.isPrepared.isprepared001a * @run driver * nsk.jdi.ReferenceType.isPrepared.isprepared001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java index c43f9ae033cf..4f7c5d488352 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isprepared001 JDI test. */ public class isprepared001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); NotPreparedClass not_prepared_class_0, not_prepared_class_1[] = {not_prepared_class_0}; @@ -43,33 +41,20 @@ public class isprepared001a { PreparedClass prepared_class_0 = new PreparedClass(); - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isprepared001a: debugee started!"); + log.display("**> isprepared001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); isprepared001a isprepared001a_obj = new isprepared001a(); - print_log_on_verbose("**> isprepared001a: waiting for \"quit\" signal..."); + log.display("**> isprepared001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isprepared001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isprepared001a: completed succesfully!"); + log.display("**> isprepared001a: \"quit\" signal recieved!"); + log.display("**> isprepared001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isprepared001a: unexpected signal (no \"quit\") - " + instruction); @@ -84,7 +69,6 @@ class NotPreparedClass {} // not prepared interface interface NotPreparedInterface {} - // prepared interface interface PreparedInterface { static final int int_var = 1; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java index 9030c57a7270..3de35d5943e1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.isPrepared.isprepared002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java index b005131cc4c6..2886c04cbf82 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isprepared002 JDI test. */ public class isprepared002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.isPrepared."; private final static String checked_class_name = package_prefix + "isprepared002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> isprepared002a: debugee started!"); + log.display("**> isprepared002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isprepared002a: waiting for \"checked class dir\" info..."); + log.display("**> isprepared002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> isprepared002a: checked class loaded: " + checked_class_name); + log.display("--> isprepared002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> isprepared002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> isprepared002a: checked class NOT loaded: " + checked_class_name); + log.display("--> isprepared002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> isprepared002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> isprepared002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isprepared002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isprepared002a: completed!"); + log.display("**> isprepared002a: \"quit\" signal recieved!"); + log.display("**> isprepared002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> isprepared002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> isprepared002a: enforce to unload checked class..."); + log.display("**> isprepared002a: \"continue\" signal recieved!"); + log.display("**> isprepared002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> isprepared002a: checked class may be NOT unloaded!"); + log.display("**> isprepared002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> isprepared002a: checked class unloaded!"); + log.display("**> isprepared002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> isprepared002a: waiting for \"quit\" signal..."); + log.display("**> isprepared002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isprepared002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isprepared002a: completed!"); + log.display("**> isprepared002a: \"quit\" signal recieved!"); + log.display("**> isprepared002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isprepared002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java index 94b2bba78b2c..689152ad2b5a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java @@ -48,7 +48,6 @@ public class isVerified001 { thisClassName = package_prefix + "isVerified001", debugeeName = thisClassName + "a"; - static ArgumentHandler argsHandler; private static Log logHandler; @@ -70,7 +69,6 @@ public class isVerified001 { }; - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -114,14 +112,10 @@ private int runThis (String argv[], PrintStream out) { print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); String debugee_launch_command = debugeeName; - if (verbose_mode) { - debugee_launch_command = debugeeName + " -vbs"; - } Debugee debugee = binder.bindToDebugee(debugee_launch_command); IOPipe pipe = new IOPipe(debugee); - debugee.redirectStderr(out); print_log_on_verbose("--> isVerified001: isVerified001a debugee launched"); debugee.resume(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java index 9b2dce7f47da..7bc6b3979c48 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java @@ -49,7 +49,6 @@ * nsk.jdi.ReferenceType.isVerified.isVerified001a * @run driver * nsk.jdi.ReferenceType.isVerified.isVerified001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java index 4f4649dd0339..bb742cf4166c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isVerified001 JDI test. */ public class isVerified001a { - static boolean verbose_mode = false; + private static Log log = new Log(System.err); isVerified001 a001_0 = new isVerified001(); @@ -46,33 +45,20 @@ public class isVerified001a { verif_subcl verif_subcl_0 = new verif_subcl(); - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i isVerified001a: debugee started!"); + log.display("**> isVerified001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); isVerified001a isVerified001a_obj = new isVerified001a(); - print_log_on_verbose("**> isVerified001a: waiting for \"quit\" signal..."); + log.display("**> isVerified001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isVerified001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isVerified001a: completed succesfully!"); + log.display("**> isVerified001a: \"quit\" signal recieved!"); + log.display("**> isVerified001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isVerified001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java index a766e7476f61..8d5f66835ae2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java @@ -64,7 +64,6 @@ * * @run driver * nsk.jdi.ReferenceType.isVerified.isverified002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java index 6a769b9c78bc..0ffd9fdc0922 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,59 +29,47 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the isverified002 JDI test. */ public class isverified002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); static String package_prefix = "nsk.jdi.ReferenceType.isVerified."; static String checked_class_name = package_prefix + "isverified002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> isverified002a: debugee started!"); + log.display("**> isverified002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> isverified002a: waiting for \"checked class dir\" info..."); + log.display("**> isverified002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; - ClassUnloader classUnloader = new ClassUnloader(); try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> isverified002a: checked class loaded: " + checked_class_name); + log.display("--> isverified002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> isverified002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> isverified002a: checked class NOT loaded: " + checked_class_name); + log.display("--> isverified002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> isverified002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> isverified002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isverified002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isverified002a: completed!"); + log.display("**> isverified002a: \"quit\" signal recieved!"); + log.display("**> isverified002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -91,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> isverified002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> isverified002a: enforce to unload checked class..."); + log.display("**> isverified002a: \"continue\" signal recieved!"); + log.display("**> isverified002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> isverified002a: checked class may be NOT unloaded!"); + log.display("**> isverified002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> isverified002a: checked class unloaded!"); + log.display("**> isverified002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> isverified002a: waiting for \"quit\" signal..."); + log.display("**> isverified002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> isverified002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> isverified002a: completed!"); + log.display("**> isverified002a: \"quit\" signal recieved!"); + log.display("**> isverified002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> isverified002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java index 84fa7f432942..663bed874885 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.methods.methods001a * @run driver * nsk.jdi.ReferenceType.methods.methods001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java index 1055d9f06079..12b8313c3046 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methods001 JDI test. */ public class methods001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.methods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methods001aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methods001a: debugee started!"); + log.display("**> methods001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, methods001a.class.getClassLoader()); - print_log_on_verbose - ("--> methods001a: checked class loaded:" + checked_class_name); + log.display("--> methods001a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> methods001a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> methods001a: checked class NOT loaded: " + checked_class_name); + log.display("--> methods001a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methods001a: waiting for \"quit\" signal..."); + log.display("**> methods001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methods001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methods001a: completed succesfully!"); + log.display("**> methods001a: \"quit\" signal recieved!"); + log.display("**> methods001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methods001a: unexpected signal (no \"quit\") - " + instruction); @@ -197,7 +180,6 @@ public void i_interf_overridden_void_par_method(int i) {} // static initializer static {} - } abstract class methods001aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java index b54e423eb70f..7569f5918825 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,6 @@ public class methods002 { static ArgumentHandler argsHandler; static Log test_log_handler; - static boolean verbose_mode = false; // test argument -verbose switches to true - // - for more easy failure evaluation /** The main class names of the debugger & debugee applications. */ private final static String @@ -55,7 +53,6 @@ public class methods002 { private final static String classLoaderName = package_prefix + "methods002aClassLoader"; private final static String classFieldName = "loadedClass"; - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -72,22 +69,14 @@ public static int run (String argv[], PrintStream out) { int v_test_result = new methods002().runThis(argv,out); if ( v_test_result == 2/*STATUS_FAILED*/ ) { - print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods002 test FAILED"); + test_log_handler.complain("\n==> nsk/jdi/ReferenceType/methods/methods002 test FAILED"); } else { - print_log_on_verbose("\n==> nsk/jdi/ReferenceType/methods/methods002 test PASSED"); + test_log_handler.display("\n==> nsk/jdi/ReferenceType/methods/methods002 test PASSED"); } return v_test_result; } - private static void print_log_on_verbose(String message) { - test_log_handler.display(message); - } - - private static void print_log_anyway(String message) { - test_log_handler.complain(message); - } - /** * Non-static variant of the method run(args,out) */ @@ -97,40 +86,33 @@ private int runThis (String argv[], PrintStream out) { test_log_handler = new Log(out, argsHandler); Binder binder = new Binder(argsHandler, test_log_handler); - print_log_on_verbose("==> nsk/jdi/ReferenceType/methods/methods002 test LOG:"); - print_log_on_verbose("==> test checks methods() method of ReferenceType interface "); - print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + test_log_handler.display("==> nsk/jdi/ReferenceType/methods/methods002 test LOG:"); + test_log_handler.display("==> test checks methods() method of ReferenceType interface "); + test_log_handler.display(" of the com.sun.jdi package for not prepared class\n"); String debugee_launch_command = debugeeName; - if (verbose_mode) { - debugee_launch_command = debugeeName + " -vbs"; - } Debugee debugee = binder.bindToDebugee(debugee_launch_command); IOPipe pipe = new IOPipe(debugee); - debugee.redirectStderr(out); - print_log_on_verbose("--> methods002: methods002a debugee launched"); + test_log_handler.display("--> methods002: methods002a debugee launched"); debugee.resume(); String line = pipe.readln(); if (line == null) { - print_log_anyway - ("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + test_log_handler.complain("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); return 2/*STATUS_FAILED*/; } if (!line.equals("ready")) { - print_log_anyway - ("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + test_log_handler.complain("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); return 2/*STATUS_FAILED*/; } else { - print_log_on_verbose("--> methods002: debugee's \"ready\" signal recieved!"); + test_log_handler.display("--> methods002: debugee's \"ready\" signal recieved!"); } - print_log_on_verbose - ("--> methods002: check ReferenceType.methods() method for not prepared " + test_log_handler.display("--> methods002: check ReferenceType.methods() method for not prepared " + class_for_check + " class..."); boolean class_not_found_error = false; boolean methods_method_error = false; @@ -138,7 +120,7 @@ private int runThis (String argv[], PrintStream out) { while ( true ) { // test body ReferenceType loaderRefType = debugee.classByName(classLoaderName); if (loaderRefType == null) { - print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + test_log_handler.complain("##> Could NOT FIND custom class loader: " + classLoaderName); class_not_found_error = true; break; } @@ -150,7 +132,7 @@ private int runThis (String argv[], PrintStream out) { try { classObjRef = (ClassObjectReference)classValue; } catch (Exception e) { - print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + test_log_handler.complain("##> Unexpected exception while getting ClassObjectReference : " + e); class_not_found_error = true; break; } @@ -158,34 +140,27 @@ private int runThis (String argv[], PrintStream out) { ReferenceType refType = classObjRef.reflectedType(); boolean isPrep = refType.isPrepared(); if (isPrep) { - print_log_anyway - ("##> methods002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + test_log_handler.complain("##> methods002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); class_not_found_error = true; break; } else { - print_log_on_verbose - ("--> methods002: isPrepared() returns for " + class_for_check + " : " + isPrep); + test_log_handler.display("--> methods002: isPrepared() returns for " + class_for_check + " : " + isPrep); } List methods_list = null; try { methods_list = refType.methods(); - print_log_anyway - ("##> methods002: FAILED: NO any Exception thrown!"); - print_log_anyway - ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + test_log_handler.complain("##> methods002: FAILED: NO any Exception thrown!"); + test_log_handler.complain("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); methods_method_error = true; } catch (Exception expt) { if (expt instanceof com.sun.jdi.ClassNotPreparedException) { - print_log_on_verbose - ("--> methods002: PASSED: expected Exception thrown - " + expt.toString()); + test_log_handler.display("--> methods002: PASSED: expected Exception thrown - " + expt.toString()); } else { - print_log_anyway - ("##> methods002: FAILED: unexpected Exception thrown - " + expt.toString()); - print_log_anyway - ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + test_log_handler.complain("##> methods002: FAILED: unexpected Exception thrown - " + expt.toString()); + test_log_handler.complain("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); methods_method_error = true; } } @@ -196,19 +171,17 @@ private int runThis (String argv[], PrintStream out) { v_test_result = 2/*STATUS_FAILED*/; } - print_log_on_verbose("--> methods002: waiting for debugee finish..."); + test_log_handler.display("--> methods002: waiting for debugee finish..."); pipe.println("quit"); debugee.waitFor(); int status = debugee.getStatus(); if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { - print_log_anyway - ("##> methods002: UNEXPECTED Debugee's exit status (not 95) - " + status); + test_log_handler.complain("##> methods002: UNEXPECTED Debugee's exit status (not 95) - " + status); v_test_result = 2/*STATUS_FAILED*/; } else { - print_log_on_verbose - ("--> methods002: expected Debugee's exit status - " + status); + test_log_handler.display("--> methods002: expected Debugee's exit status - " + status); } return v_test_result; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java index b8957fb1c0ee..c5e211ec5724 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.methods.methods002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java index 8ac4f767fe1c..50c2980102e2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,30 +34,16 @@ public class methods002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methods002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methods002a: debugee started!"); + log.display("**> methods002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -66,19 +52,17 @@ public static void main (String argv[]) { methods002aClassLoader customClassLoader = new methods002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> methods002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> methods002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> methods002a: checked class NOT loaded: " + e); + log.display("--> methods002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> methods002a: waiting for \"quit\" signal..."); + log.display("**> methods002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methods002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methods002a: completed succesfully!"); + log.display("**> methods002a: \"quit\" signal recieved!"); + log.display("**> methods002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methods002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java index 5a37d7e66a4e..f102e1281024 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java @@ -61,7 +61,6 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run driver * nsk.jdi.ReferenceType.methods.methods003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java index 0e8c2e3399cb..54a2bbe000b7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methods003 JDI test. */ public class methods003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methods."; private final static String checked_class_name = package_prefix + "methods003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> methods003a: debugee started!"); + log.display("**> methods003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> methods003a: waiting for \"checked class dir\" info..."); + log.display("**> methods003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> methods003a: checked class loaded:" + checked_class_name); + log.display("--> methods003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> methods003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> methods003a: checked class NOT loaded:" + checked_class_name); + log.display("--> methods003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methods003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> methods003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methods003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methods003a: completed!"); + log.display("**> methods003a: \"quit\" signal recieved!"); + log.display("**> methods003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> methods003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> methods003a: enforce to unload checked class..."); + log.display("**> methods003a: \"continue\" signal recieved!"); + log.display("**> methods003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> methods003a: checked class may be NOT unloaded!"); + log.display("**> methods003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> methods003a: checked class unloaded!"); + log.display("**> methods003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> methods003a: waiting for \"quit\" signal..."); + log.display("**> methods003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methods003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methods003a: completed!"); + log.display("**> methods003a: \"quit\" signal recieved!"); + log.display("**> methods003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methods003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java index 25778f2f00c3..d6464f4645db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.methods.methods004a * @run driver * nsk.jdi.ReferenceType.methods.methods004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java index 41c1dec7e5eb..8f3d95cefc7f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methods004 JDI test. */ public class methods004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i methods004a: debugee started!"); + log.display("**> methods004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); methods004aClassForCheck class_for_check = new methods004aClassForCheck(); - print_log_on_verbose("**> methods004a: waiting for \"quit\" signal..."); + log.display("**> methods004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methods004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methods004a: completed succesfully!"); + log.display("**> methods004a: \"quit\" signal recieved!"); + log.display("**> methods004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> methods004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java index 11dd886ea201..a16a9c936d4a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s001a * @run driver * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java index 54290e729455..1fb31279c6f3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methbyname_s001 JDI test. */ public class methbyname_s001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methbyname_s001aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methbyname_s001a: debugee started!"); + log.display("**> methbyname_s001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, methbyname_s001a.class.getClassLoader()); - print_log_on_verbose - ("--> methbyname_s001a: checked class loaded:" + checked_class_name); + log.display("--> methbyname_s001a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> methbyname_s001a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> methbyname_s001a: checked class NOT loaded: " + checked_class_name); + log.display("--> methbyname_s001a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methbyname_s001a: waiting for \"quit\" signal..."); + log.display("**> methbyname_s001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_s001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_s001a: completed succesfully!"); + log.display("**> methbyname_s001a: \"quit\" signal recieved!"); + log.display("**> methbyname_s001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_s001a: unexpected signal (no \"quit\") - " + instruction); @@ -193,11 +176,9 @@ public void i_interf_overridden_void_par_method(int i) {} protected Object i_protected_method(Object obj) {return new Object();} public Object i_public_method(Object obj) {return new Object();} - // static initializer static {} - } abstract class methbyname_s001aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java index 57663947dd15..2917004d0977 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java @@ -57,8 +57,6 @@ public class methbyname_s002 { static ArgumentHandler argsHandler; private static Log logHandler; - - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -97,18 +95,13 @@ private void print_log_anyway(String message) { */ private int runThis (String argv[], PrintStream out) { - argsHandler = new ArgumentHandler(argv); logHandler = new Log(out, argsHandler); Binder binder = new Binder(argsHandler, logHandler); Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002 test LOG:"); print_log_on_verbose("==> test checks methodsByName(String name) method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java index bdfe397adf30..5563e139b1fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java index fd2377ccb7d6..2df2a86c6379 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the methbyname_s002 JDI test. */ public class methbyname_s002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methbyname_s002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methbyname_s002a: debugee started!"); + log.display("**> methbyname_s002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { methbyname_s002aClassLoader customClassLoader = new methbyname_s002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> methbyname_s002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> methbyname_s002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> methbyname_s002a: checked class NOT loaded: " + e); + log.display("--> methbyname_s002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> methbyname_s002a: waiting for \"quit\" signal..."); + log.display("**> methbyname_s002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_s002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_s002a: completed succesfully!"); + log.display("**> methbyname_s002a: \"quit\" signal recieved!"); + log.display("**> methbyname_s002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_s002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java index 6f70f225a147..234d205cca44 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java index 5ef8e69611ed..9ee25a400a21 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methbyname_s003 JDI test. */ public class methbyname_s003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; private final static String checked_class_name = package_prefix + "methbyname_s003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> methbyname_s003a: debugee started!"); + log.display("**> methbyname_s003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> methbyname_s003a: waiting for \"checked class dir\" info..."); + log.display("**> methbyname_s003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> methbyname_s003a: checked class loaded:" + checked_class_name); + log.display("--> methbyname_s003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> methbyname_s003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> methbyname_s003a: checked class NOT loaded:" + checked_class_name); + log.display("--> methbyname_s003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methbyname_s003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> methbyname_s003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_s003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_s003a: completed!"); + log.display("**> methbyname_s003a: \"quit\" signal recieved!"); + log.display("**> methbyname_s003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> methbyname_s003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> methbyname_s003a: enforce to unload checked class..."); + log.display("**> methbyname_s003a: \"continue\" signal recieved!"); + log.display("**> methbyname_s003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> methbyname_s003a: checked class may be NOT unloaded!"); + log.display("**> methbyname_s003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> methbyname_s003a: checked class unloaded!"); + log.display("**> methbyname_s003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> methbyname_s003a: waiting for \"quit\" signal..."); + log.display("**> methbyname_s003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_s003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_s003a: completed!"); + log.display("**> methbyname_s003a: \"quit\" signal recieved!"); + log.display("**> methbyname_s003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_s003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java index c0e9a10a0988..c3269eb22957 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s004a * @run driver * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java index 24ea124d6c47..9edec597fea5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methbyname_s004 JDI test. */ public class methbyname_s004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methbyname_s004aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methbyname_s004a: debugee started!"); + log.display("**> methbyname_s004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, methbyname_s004a.class.getClassLoader()); - print_log_on_verbose - ("--> methbyname_s004a: checked class loaded:" + checked_class_name); + log.display("--> methbyname_s004a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> methbyname_s004a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> methbyname_s004a: checked class NOT loaded: " + checked_class_name); + log.display("--> methbyname_s004a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methbyname_s004a: waiting for \"quit\" signal..."); + log.display("**> methbyname_s004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_s004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_s004a: completed succesfully!"); + log.display("**> methbyname_s004a: \"quit\" signal recieved!"); + log.display("**> methbyname_s004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_s004a: unexpected signal (no \"quit\") - " + instruction); @@ -92,7 +75,6 @@ public static void main (String argv[]) { abstract class methbyname_s004aClassForCheck extends methbyname_s004aSuperClassForCheck implements methbyname_s004aInterfaceForCheck { - // overloaded static methods static void s_overloaded_method() {} static String s_overloaded_method(String s) {return "string";} @@ -110,7 +92,6 @@ void i_overloaded_method() {} Object i_super_overloaded_method(long l, String s) {return new Object();} Object i_interf_overloaded_method(long l, String s) {return new Object();} - } abstract class methbyname_s004aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java index de09aec27ff7..15d10c0ce975 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss001a * @run driver * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java index 13cfdf259019..a8f1589da711 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methbyname_ss001 JDI test. */ public class methbyname_ss001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methbyname_ss001aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methbyname_ss001a: debugee started!"); + log.display("**> methbyname_ss001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, methbyname_ss001a.class.getClassLoader()); - print_log_on_verbose - ("--> methbyname_ss001a: checked class loaded:" + checked_class_name); + log.display("--> methbyname_ss001a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> methbyname_ss001a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> methbyname_ss001a: checked class NOT loaded: " + checked_class_name); + log.display("--> methbyname_ss001a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methbyname_ss001a: waiting for \"quit\" signal..."); + log.display("**> methbyname_ss001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_ss001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_ss001a: completed succesfully!"); + log.display("**> methbyname_ss001a: \"quit\" signal recieved!"); + log.display("**> methbyname_ss001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_ss001a: unexpected signal (no \"quit\") - " + instruction); @@ -194,7 +177,6 @@ public void i_interf_overridden_void_par_method(int i) {} protected Object i_protected_method(Object obj) {return new Object();} public Object i_public_method(Object obj) {return new Object();} - // static initializer static {} @@ -215,7 +197,6 @@ void i_overloaded_method() {} Object i_super_overloaded_method(long l, String s) {return new Object();} Object i_interf_overloaded_method(long l, String s) {return new Object();} - } abstract class methbyname_ss001aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java index 4fdd23afb729..6b3b538ff299 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java @@ -57,8 +57,6 @@ public class methbyname_ss002 { static ArgumentHandler argsHandler; private static Log logHandler; - - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -103,11 +101,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002 test LOG:"); print_log_on_verbose("==> test checks methodsByName(String name, String signature) method of ReferenceType "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java index 0113bf81f931..632873e59c1c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java index 88dbe5521aec..c207d87c7eb1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the methbyname_ss002 JDI test. */ public class methbyname_ss002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "methbyname_ss002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i methbyname_ss002a: debugee started!"); + log.display("**> methbyname_ss002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { methbyname_ss002aClassLoader customClassLoader = new methbyname_ss002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> methbyname_ss002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> methbyname_ss002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> methbyname_ss002a: checked class NOT loaded: " + e); + log.display("--> methbyname_ss002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> methbyname_ss002a: waiting for \"quit\" signal..."); + log.display("**> methbyname_ss002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_ss002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_ss002a: completed succesfully!"); + log.display("**> methbyname_ss002a: \"quit\" signal recieved!"); + log.display("**> methbyname_ss002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_ss002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java index baf8931a6364..37e4026d4848 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java index 57906353d8a5..fa6a940052c9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the methbyname_ss003 JDI test. */ public class methbyname_ss003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; private final static String checked_class_name = package_prefix + "methbyname_ss003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> methbyname_ss003a: debugee started!"); + log.display("**> methbyname_ss003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> methbyname_ss003a: waiting for \"checked class dir\" info..."); + log.display("**> methbyname_ss003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> methbyname_ss003a: checked class loaded:" + checked_class_name); + log.display("--> methbyname_ss003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> methbyname_ss003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> methbyname_ss003a: checked class NOT loaded:" + checked_class_name); + log.display("--> methbyname_ss003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> methbyname_ss003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> methbyname_ss003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_ss003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_ss003a: completed!"); + log.display("**> methbyname_ss003a: \"quit\" signal recieved!"); + log.display("**> methbyname_ss003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> methbyname_ss003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> methbyname_ss003a: enforce to unload checked class..."); + log.display("**> methbyname_ss003a: \"continue\" signal recieved!"); + log.display("**> methbyname_ss003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> methbyname_ss003a: checked class may be NOT unloaded!"); + log.display("**> methbyname_ss003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> methbyname_ss003a: checked class unloaded!"); + log.display("**> methbyname_ss003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> methbyname_ss003a: waiting for \"quit\" signal..."); + log.display("**> methbyname_ss003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> methbyname_ss003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> methbyname_ss003a: completed!"); + log.display("**> methbyname_ss003a: \"quit\" signal recieved!"); + log.display("**> methbyname_ss003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> methbyname_ss003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java index 77b7eb38ad8e..1fb3839629c0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.name.name001a * @run driver * nsk.jdi.ReferenceType.name.name001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java index 7525f8b96e91..acbb6c6c7724 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,16 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the name001 JDI test. */ public class name001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - + private static Log log = new Log(System.err); boolean z0, z1[]={z0}, z2[][]={z1}; byte b0, b1[]={b0}, b2[][]={b1}; @@ -77,33 +74,20 @@ static class s_interf_impl implements s_interf {} interf_for_check1[]={interf_for_check0}, interf_for_check2[][]={interf_for_check1}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i name001a: debugee started!"); + log.display("**> name001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); name001a name001a_obj = new name001a(); - print_log_on_verbose("**> name001a: waiting for \"quit\" signal..."); + log.display("**> name001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> name001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> name001a: completed succesfully!"); + log.display("**> name001a: \"quit\" signal recieved!"); + log.display("**> name001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> name001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java index 927e07929b48..58475e2de8ba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.name.name002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java index 385056310fb5..c8f1dac1dbdb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the name002 JDI test. */ public class name002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.name."; private final static String checked_class_name = package_prefix + "name002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> name002a: debugee started!"); + log.display("**> name002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> name002a: waiting for \"checked class dir\" info..."); + log.display("**> name002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> name002a: checked class loaded: " + checked_class_name); + log.display("--> name002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> name002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> name002a: checked class NOT loaded: " + checked_class_name); + log.display("--> name002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> name002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> name002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> name002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> name002a: completed!"); + log.display("**> name002a: \"quit\" signal recieved!"); + log.display("**> name002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> name002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> name002a: enforce to unload checked class..."); + log.display("**> name002a: \"continue\" signal recieved!"); + log.display("**> name002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> name002a: checked class may be NOT unloaded!"); + log.display("**> name002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> name002a: checked class unloaded!"); + log.display("**> name002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> name002a: waiting for \"quit\" signal..."); + log.display("**> name002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> name002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> name002a: completed!"); + log.display("**> name002a: \"quit\" signal recieved!"); + log.display("**> name002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> name002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java index 23b6da5bd0a1..cbff28ba6d25 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.sourceName.sourcename001a * @run driver * nsk.jdi.ReferenceType.sourceName.sourcename001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java index b6d6e49b9ce9..e4e10e328b47 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the sourcename001 JDI test. */ public class sourcename001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); // Classes must be loaded and linked, so all fields must be // initialized @@ -58,33 +56,20 @@ static class s_interf_impl implements s_interf {} sourcename001 sourcename001_0 = new sourcename001(), sourcename001_1[]={sourcename001_0}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i sourcename001a: debugee started!"); + log.display("**> sourcename001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); sourcename001a sourcename001a_obj = new sourcename001a(); - print_log_on_verbose("**> sourcename001a: waiting for \"quit\" signal..."); + log.display("**> sourcename001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> sourcename001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> sourcename001a: completed succesfully!"); + log.display("**> sourcename001a: \"quit\" signal recieved!"); + log.display("**> sourcename001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> sourcename001a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java index 543272a52f0f..b30db9c9c937 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.sourceName.sourcename002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java index dcb2f8ec75f3..57e291a394ad 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the sourcename002 JDI test. */ public class sourcename002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.sourceName."; private final static String checked_class_name = package_prefix + "sourcename002b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> sourcename002a: debugee started!"); + log.display("**> sourcename002a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> sourcename002a: waiting for \"checked class dir\" info..."); + log.display("**> sourcename002a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,20 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> sourcename002a: checked class loaded: " + checked_class_name); + log.display("--> sourcename002a: checked class loaded: " + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException - print_log_on_verbose - ("**> sourcename002a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> sourcename002a: checked class NOT loaded: " + checked_class_name); + log.display("**> sourcename002a: load class: exception thrown = " + e.toString()); + log.display("--> sourcename002a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> sourcename002a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> sourcename002a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> sourcename002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> sourcename002a: completed!"); + log.display("**> sourcename002a: \"quit\" signal recieved!"); + log.display("**> sourcename002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +78,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> sourcename002a: \"continue\" signal recieved!"); - print_log_on_verbose("**> sourcename002a: enforce to unload checked class..."); + log.display("**> sourcename002a: \"continue\" signal recieved!"); + log.display("**> sourcename002a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> sourcename002a: checked class may be NOT unloaded!"); + log.display("**> sourcename002a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> sourcename002a: checked class unloaded!"); + log.display("**> sourcename002a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> sourcename002a: waiting for \"quit\" signal..."); + log.display("**> sourcename002a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> sourcename002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> sourcename002a: completed!"); + log.display("**> sourcename002a: \"quit\" signal recieved!"); + log.display("**> sourcename002a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> sourcename002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java index ab5624f9332c..f8b900ef6d92 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java @@ -46,7 +46,6 @@ * nsk.jdi.ReferenceType.sourceName.sourcename003a * @run driver * nsk.jdi.ReferenceType.sourceName.sourcename003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java index 3bdeddb3ec3b..f51a76fe342b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,45 +27,30 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the sourcename003 JDI test. */ public class sourcename003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); sourcename003 sourcename003_0, sourcename003_1[]={sourcename003_0}; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i sourcename003a: debugee started!"); + log.display("**> sourcename003a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); sourcename003a sourcename003a_obj = new sourcename003a(); - print_log_on_verbose("**> sourcename003a: waiting for \"quit\" signal..."); + log.display("**> sourcename003a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> sourcename003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> sourcename003a: completed succesfully!"); + log.display("**> sourcename003a: \"quit\" signal recieved!"); + log.display("**> sourcename003a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> sourcename003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java index 6e1e570c6c54..3ca6b0382034 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java @@ -48,7 +48,6 @@ * nsk.jdi.ReferenceType.visibleFields.visibfield001a * @run driver * nsk.jdi.ReferenceType.visibleFields.visibfield001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java index 208a73ad90ab..8dca099e1d92 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibfield001 JDI test. */ public class visibfield001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i visibfield001a: debugee started!"); + log.display("**> visibfield001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); visibfield001aClassForCheck class_for_check = new visibfield001aClassForCheck(); - print_log_on_verbose("**> visibfield001a: waiting for \"quit\" signal..."); + log.display("**> visibfield001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibfield001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibfield001a: completed succesfully!"); + log.display("**> visibfield001a: \"quit\" signal recieved!"); + log.display("**> visibfield001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibfield001a: unexpected signal (no \"quit\") - " + instruction); @@ -159,5 +143,4 @@ interface visibfield001aInterfaceForCheck { static final long ambiguous_prim_field = 1; static final Object ambiguous_ref_field = new Object(); - } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java index 1e11aac9eba6..4d067036628c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java @@ -57,8 +57,6 @@ public class visibfield002 { static ArgumentHandler argsHandler; private static Log logHandler; - - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -103,11 +101,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/visibleFields/visibfield002 test LOG:"); print_log_on_verbose("==> test checks visibleFields() method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java index fb417aa7a1d9..f469c4431f6a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.visibleFields.visibfield002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java index b8b7ac9f5918..da0845966d5f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the visibfield002 JDI test. */ public class visibfield002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.visibleFields."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "visibfield002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i visibfield002a: debugee started!"); + log.display("**> visibfield002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { visibfield002aClassLoader customClassLoader = new visibfield002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> visibfield002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> visibfield002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> visibfield002a: checked class NOT loaded: " + e); + log.display("--> visibfield002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> visibfield002a: waiting for \"quit\" signal..."); + log.display("**> visibfield002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibfield002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibfield002a: completed succesfully!"); + log.display("**> visibfield002a: \"quit\" signal recieved!"); + log.display("**> visibfield002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibfield002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java index f349deaad85a..fbc145a86e2a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.visibleFields.visibfield003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java index 56be764f85b5..7615bbbe93ed 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibfield003 JDI test. */ public class visibfield003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.visibleFields."; private final static String checked_class_name = package_prefix + "visibfield003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> visibfield003a: debugee started!"); + log.display("**> visibfield003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> visibfield003a: waiting for \"checked class dir\" info..."); + log.display("**> visibfield003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> visibfield003a: checked class loaded:" + checked_class_name); + log.display("--> visibfield003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> visibfield003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> visibfield003a: checked class NOT loaded:" + checked_class_name); + log.display("--> visibfield003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> visibfield003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> visibfield003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibfield003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibfield003a: completed!"); + log.display("**> visibfield003a: \"quit\" signal recieved!"); + log.display("**> visibfield003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> visibfield003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> visibfield003a: enforce to unload checked class..."); + log.display("**> visibfield003a: \"continue\" signal recieved!"); + log.display("**> visibfield003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> visibfield003a: checked class may be NOT unloaded!"); + log.display("**> visibfield003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> visibfield003a: checked class unloaded!"); + log.display("**> visibfield003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> visibfield003a: waiting for \"quit\" signal..."); + log.display("**> visibfield003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibfield003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibfield003a: completed!"); + log.display("**> visibfield003a: \"quit\" signal recieved!"); + log.display("**> visibfield003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibfield003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java index 5f3584cbd91b..bc0f60811143 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.visibleFields.visibfield004a * @run driver * nsk.jdi.ReferenceType.visibleFields.visibfield004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java index acca91d0c439..773f8f7e5ed5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibfield004 JDI test. */ public class visibfield004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i visibfield004a: debugee started!"); + log.display("**> visibfield004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); visibfield004aClassForCheck class_for_check = new visibfield004aClassForCheck(); - print_log_on_verbose("**> visibfield004a: waiting for \"quit\" signal..."); + log.display("**> visibfield004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibfield004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibfield004a: completed succesfully!"); + log.display("**> visibfield004a: \"quit\" signal recieved!"); + log.display("**> visibfield004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> visibfield004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java index 08379613165f..2a1a0de8997f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.visibleMethods.visibmethod001a * @run driver * nsk.jdi.ReferenceType.visibleMethods.visibmethod001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java index 723b65577c77..127263b16375 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibmethod001 JDI test. */ public class visibmethod001a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "visibmethod001aClassForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i visibmethod001a: debugee started!"); + log.display("**> visibmethod001a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, visibmethod001a.class.getClassLoader()); - print_log_on_verbose - ("--> visibmethod001a: checked class loaded:" + checked_class_name); + log.display("--> visibmethod001a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> visibmethod001a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> visibmethod001a: checked class NOT loaded: " + checked_class_name); + log.display("--> visibmethod001a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> visibmethod001a: waiting for \"quit\" signal..."); + log.display("**> visibmethod001a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod001a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod001a: completed succesfully!"); + log.display("**> visibmethod001a: \"quit\" signal recieved!"); + log.display("**> visibmethod001a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibmethod001a: unexpected signal (no \"quit\") - " + instruction); @@ -197,7 +180,6 @@ public void i_interf_overridden_void_par_method(int i) {} // static initializer static {} - } abstract class visibmethod001aSuperClassForCheck { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java index b8c2d032c315..7ca700382c1c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java @@ -57,8 +57,6 @@ public class visibmethod002 { static ArgumentHandler argsHandler; private static Log logHandler; - - public static void main (String argv[]) { int result = run(argv,System.out); if (result != 0) { @@ -103,11 +101,7 @@ private int runThis (String argv[], PrintStream out) { Debugee debugee; - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); - } else { - debugee = binder.bindToDebugee(debugeeName); - } + debugee = binder.bindToDebugee(debugeeName); print_log_on_verbose("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod002 test LOG:"); print_log_on_verbose("==> test checks visibleMethods() method of ReferenceType interface "); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java index 72978fd9bc3b..3ac38c675dde 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java @@ -56,7 +56,6 @@ * * @run driver * nsk.jdi.ReferenceType.visibleMethods.visibmethod002 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java index 4f219b75cf1c..87e27bb95d24 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,37 +28,22 @@ import nsk.share.jdi.*; import java.io.*; - /** * This class is used as debugee application for the visibmethod002 JDI test. */ public class visibmethod002a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "visibmethod002aClassForCheck"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i visibmethod002a: debugee started!"); + log.display("**> visibmethod002a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -67,19 +52,17 @@ public static void main (String argv[]) { visibmethod002aClassLoader customClassLoader = new visibmethod002aClassLoader(checked_class_dir, checked_class_name); try { customClassLoader.preloadClass(checked_class_name); - print_log_on_verbose - ("--> visibmethod002a: checked class loaded but not prepared: " + checked_class_name); + log.display("--> visibmethod002a: checked class loaded but not prepared: " + checked_class_name); } catch (Throwable e) { // ClassNotFoundException - print_log_on_verbose - ("--> visibmethod002a: checked class NOT loaded: " + e); + log.display("--> visibmethod002a: checked class NOT loaded: " + e); } - print_log_on_verbose("**> visibmethod002a: waiting for \"quit\" signal..."); + log.display("**> visibmethod002a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod002a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod002a: completed succesfully!"); + log.display("**> visibmethod002a: \"quit\" signal recieved!"); + log.display("**> visibmethod002a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibmethod002a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java index c6de37e2939f..19afceedbf03 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java @@ -62,7 +62,6 @@ * * @run driver * nsk.jdi.ReferenceType.visibleMethods.visibmethod003 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java index b04195f51d30..421cd5780377 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,34 +29,25 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibmethod003 JDI test. */ public class visibmethod003a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); private final static String package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; private final static String checked_class_name = package_prefix + "visibmethod003b"; - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { ArgumentHandler argHandler = new ArgumentHandler(argv); - verbose_mode = argHandler.verbose(); - print_log_on_verbose("**> visibmethod003a: debugee started!"); + log.display("**> visibmethod003a: debugee started!"); IOPipe pipe = argHandler.createDebugeeIOPipe(); - print_log_on_verbose("**> visibmethod003a: waiting for \"checked class dir\" info..."); + log.display("**> visibmethod003a: waiting for \"checked class dir\" info..."); pipe.println("ready0"); String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; @@ -64,23 +55,21 @@ public static void main (String argv[]) { try { classUnloader.loadClass(checked_class_name, checked_class_dir); - print_log_on_verbose - ("--> visibmethod003a: checked class loaded:" + checked_class_name); + log.display("--> visibmethod003a: checked class loaded:" + checked_class_name); } catch ( Exception e ) { // ClassNotFoundException System.err.println ("**> visibmethod003a: load class: exception thrown = " + e.toString()); - print_log_on_verbose - ("--> visibmethod003a: checked class NOT loaded:" + checked_class_name); + log.display("--> visibmethod003a: checked class NOT loaded:" + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> visibmethod003a: waiting for \"continue\" or \"quit\" signal..."); + log.display("**> visibmethod003a: waiting for \"continue\" or \"quit\" signal..."); pipe.println("ready1"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod003a: completed!"); + log.display("**> visibmethod003a: \"quit\" signal recieved!"); + log.display("**> visibmethod003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } if ( ! instruction.equals("continue")) { @@ -90,24 +79,24 @@ public static void main (String argv[]) { System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); } - print_log_on_verbose("**> visibmethod003a: \"continue\" signal recieved!"); - print_log_on_verbose("**> visibmethod003a: enforce to unload checked class..."); + log.display("**> visibmethod003a: \"continue\" signal recieved!"); + log.display("**> visibmethod003a: enforce to unload checked class..."); boolean test_class_loader_finalized = classUnloader.unloadClass(); if ( ! test_class_loader_finalized ) { - print_log_on_verbose("**> visibmethod003a: checked class may be NOT unloaded!"); + log.display("**> visibmethod003a: checked class may be NOT unloaded!"); pipe.println("not_unloaded"); } else { - print_log_on_verbose("**> visibmethod003a: checked class unloaded!"); + log.display("**> visibmethod003a: checked class unloaded!"); pipe.println("ready2"); } - print_log_on_verbose("**> visibmethod003a: waiting for \"quit\" signal..."); + log.display("**> visibmethod003a: waiting for \"quit\" signal..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod003a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod003a: completed!"); + log.display("**> visibmethod003a: \"quit\" signal recieved!"); + log.display("**> visibmethod003a: completed!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibmethod003a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java index ebbcfcaeff48..0f4d7dbebb71 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java @@ -45,7 +45,6 @@ * nsk.jdi.ReferenceType.visibleMethods.visibmethod004a * @run driver * nsk.jdi.ReferenceType.visibleMethods.visibmethod004 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java index 61c2160f7944..8a58e461060d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,44 +27,28 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibmethod004 JDI test. */ public class visibmethod004a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation - - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } + private static Log log = new Log(System.err); public static void main (String argv[]) { - for (int i=0; i visibmethod004a: debugee started!"); + log.display("**> visibmethod004a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); visibmethod004aClassForCheck class_for_check = new visibmethod004aClassForCheck(); - print_log_on_verbose("**> visibmethod004a: waiting for \"quit\" signal..."); + log.display("**> visibmethod004a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod004a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod004a: completed succesfully!"); + log.display("**> visibmethod004a: \"quit\" signal recieved!"); + log.display("**> visibmethod004a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("##> visibmethod004a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java index 5d8711f225dd..5a611156bc00 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java @@ -47,7 +47,6 @@ * nsk.jdi.ReferenceType.visibleMethods.visibmethod005a * @run driver * nsk.jdi.ReferenceType.visibleMethods.visibmethod005 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java index a1c74711229f..77ab28aea36e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the visibmethod005 JDI test. */ public class visibmethod005a { - static boolean verbose_mode = false; // debugger may switch to true - // - for more easy failure evaluation + private static Log log = new Log(System.err); + private final static String package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; // package_prefix = ""; // for DEBUG without package static String checked_class_name = package_prefix + "visibmethod005aInterfaceForCheck"; - - private static void print_log_on_verbose(String message) { - if ( verbose_mode ) { - System.err.println(message); - } - } - public static void main (String argv[]) { - for (int i=0; i visibmethod005a: debugee started!"); + log.display("**> visibmethod005a: debugee started!"); ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); @@ -65,23 +50,21 @@ public static void main (String argv[]) { try { checked_class_classobj = Class.forName(checked_class_name, true, visibmethod005a.class.getClassLoader()); - print_log_on_verbose - ("--> visibmethod005a: checked class loaded:" + checked_class_name); + log.display("--> visibmethod005a: checked class loaded:" + checked_class_name); } catch ( Throwable thrown ) { // ClassNotFoundException // System.err.println // ("**> visibmethod005a: load class: Throwable thrown = " + thrown.toString()); - print_log_on_verbose - ("--> visibmethod005a: checked class NOT loaded: " + checked_class_name); + log.display("--> visibmethod005a: checked class NOT loaded: " + checked_class_name); // Debuuger finds this fact itself } - print_log_on_verbose("**> visibmethod005a: waiting for \"quit\" signal..."); + log.display("**> visibmethod005a: waiting for \"quit\" signal..."); pipe.println("ready"); String instruction = pipe.readln(); if (instruction.equals("quit")) { - print_log_on_verbose("**> visibmethod005a: \"quit\" signal recieved!"); - print_log_on_verbose("**> visibmethod005a: completed succesfully!"); + log.display("**> visibmethod005a: \"quit\" signal recieved!"); + log.display("**> visibmethod005a: completed succesfully!"); System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); } System.err.println("!!**> visibmethod005a: unexpected signal (no \"quit\") - " + instruction); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002.java index 02a87d9c42b4..e52a7421383f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,15 +38,16 @@ * The test checks that the JDI method:
com.sun.jdi.ThreadReference.stop()
* behaves properly in various situations. It consists of 5 subtests. * - * TEST #1: Tests that stop() properly throws InvalidTypeException if - * specified throwable is not an instance of java.lang.Throwable in the target VM.

+ * TEST #1: Tests that stop() properly throws InvalidTypeException if + * specified throwable is not an instance of java.lang.Throwable in the target VM. * * TEST #2: Verify that stop() works when suspended at a breakpoint. * * TEST #3: Verify that stop() works when not suspended in a loop. For virtual threads * we expect an IncompatibleThreadStateException. * - * TEST #4: Verify that stop() works when suspended in a loop. + * TEST #4: Verify that stop() works when suspended in a loop. For Virtual threads + * we may get OpaqueFrameException. * * TEST #5: Verify that stop() works when suspended in Thread.sleep(). For virtual * threads we expect an OpaqueFrameException. @@ -65,9 +66,11 @@ public class stop002 { // debuggee fields used to indicate to exit infinite loops static final String DEBUGGEE_STOP_LOOP1_FIELD = "stopLooping1"; static final String DEBUGGEE_STOP_LOOP2_FIELD = "stopLooping2"; + // debuggee field used to indicate that debugger got OpaqueFrameException + static final String DEBUGGEE_GOT_OFE_FIELD = "gotOpaqueFrameException"; // debuggee source line where it should be stopped - static final int DEBUGGEE_STOPATLINE = 90; + static final int DEBUGGEE_STOPATLINE = 91; static final int DELAY = 500; // in milliseconds @@ -117,6 +120,7 @@ private int runIt(String args[], PrintStream out) { Field stopLoop1 = null; Field stopLoop2 = null; + Field gotOpaqueFrameException = null; ObjectReference objRef = null; ObjectReference throwableRef = null; @@ -143,6 +147,11 @@ private int runIt(String args[], PrintStream out) { throw new RuntimeException("Failed to find a \"stop loop\" field"); } + gotOpaqueFrameException = mainClass.fieldByName(DEBUGGEE_GOT_OFE_FIELD); + if (gotOpaqueFrameException == null) { + throw new RuntimeException("Failed to find a \"gotOpaqueFrameException\" field"); + } + log.display("non-throwable object: \"" + objRef + "\""); log.display("throwable object: \"" + throwableRef + "\""); log.display("debuggee thread: \"" + thrRef + "\""); @@ -205,8 +214,7 @@ private int runIt(String args[], PrintStream out) { tot_res = Consts.TEST_FAILED; } } finally { - // Force the debuggee out of the loop. Not really needed if the stop() call - // successfully threw the async exception, but it's easier to just always do this. + // Make sure the debuggee exits the loop even if the async exception was not thrown. log.display("TEST #3: clearing loop flag."); objRef.setValue(stopLoop1, vm.mirrorOf(true)); } @@ -222,15 +230,25 @@ private int runIt(String args[], PrintStream out) { log.display("TEST #4: thread is suspended."); thrRef.stop(throwableRef); log.display("TEST #4 PASSED: stop() call succeeded."); + objRef.setValue(gotOpaqueFrameException, vm.mirrorOf(false)); + } catch (OpaqueFrameException ofe) { + if (vthreadMode) { + log.display("TEST #4 PASSED: stop() call resulted in OpaqueFrameException while in vthread mode."); + } else { + ofe.printStackTrace(); + log.complain("TEST #4 FAILED: caught unexpected " + ofe); + tot_res = Consts.TEST_FAILED; + } + objRef.setValue(gotOpaqueFrameException, vm.mirrorOf(true)); } catch (Throwable ue) { ue.printStackTrace(); log.complain("TEST #4 FAILED: caught unexpected " + ue); tot_res = Consts.TEST_FAILED; + objRef.setValue(gotOpaqueFrameException, vm.mirrorOf(false)); } finally { log.display("TEST #4: resuming thread."); thrRef.resume(); - // Force the debuggee out of the loop. Not really needed if the stop() call - // successfully threw the async exception, but it's easier to just always do this. + // Make sure the debuggee exits the loop even if the async exception was not thrown. log.display("TEST #4: clearing loop flag."); objRef.setValue(stopLoop2, vm.mirrorOf(true)); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java index 0d87338f6781..2bfc82f9fac8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java @@ -37,6 +37,7 @@ public class stop002t { private IOPipe pipe; volatile boolean stopLooping1 = false; volatile boolean stopLooping2 = false; + volatile boolean gotOpaqueFrameException = false; volatile static int testNumReady = 0; static final boolean vthreadMode = "Virtual".equals(System.getProperty("test.thread.factory")); static Thread testThread = null; @@ -139,8 +140,19 @@ private int runIt(String args[]) { testNumReady = 4; // signal debugger side of test that we are ready stopMeHere++; stopMeHere--; } - log.complain("TEST #4: Failed to throw expected exception"); - return Consts.TEST_FAILED; + if (vthreadMode) { + if (gotOpaqueFrameException) { + // Exception not required when in vthread mode if OpaqueFrameException thrown + log.display("TEST #4: threw OpaqueFrameException while in vthread mode"); + } else { + log.complain("TEST #4: Failed to throw expected exception and " + + "failed to throw debugger side OpaqueFrameException"); + return Consts.TEST_FAILED; + } + } else { + log.complain("TEST #4: Failed to throw expected exception"); + return Consts.TEST_FAILED; + } } catch (Throwable t) { // Call Thread.interrupted(). Workaround for JDK-8306324 log.display("TEST #4: interrupted = " + Thread.interrupted()); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java index da26eb37857b..af705bd47201 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java @@ -119,11 +119,7 @@ private int runThis (String argv[], PrintStream out) { logHandler = new Log(out, argsHandler); Binder binder = new Binder(argsHandler, logHandler); - if (argsHandler.verbose()) { - debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp - } else { - debugee = binder.bindToDebugee(debugeeName); // *** tp - } + debugee = binder.bindToDebugee(debugeeName); IOPipe pipe = new IOPipe(debugee); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java index 93b28f0daf1f..bb322adc1979 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java @@ -63,7 +63,6 @@ * nsk.jdi.VirtualMachine.classesByName.classesbyname001a * @run driver * nsk.jdi.VirtualMachine.classesByName.classesbyname001 - * -verbose * -arch=${os.family}-${os.simpleArch} * -waittime=5 * -debugee.vmkind=java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java index 470263e5e9bc..476c3c53a2ac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,34 +27,22 @@ import nsk.share.jpda.*; import nsk.share.jdi.*; - /** * This class is used as debugee application for the classesbyname001 JDI test. */ public class classesbyname001a { + private static Log log = new Log(System.err); + //----------------------------------------------------- template section static final int PASSED = 0; static final int FAILED = 2; static final int PASS_BASE = 95; - //-------------------------------------------------- log procedures - static boolean verbose_mode = false; // debugger may switch to true - - private static void log1(String message) { - if (verbose_mode) - System.err.println("**> classesbyname001a: " + message); - } - - private static void logErr(String message) { - if (verbose_mode) - System.err.println("!!**> classesbyname001a: " + message); - } - //====================================================== test program //------------------------------------------------------ common section @@ -63,28 +51,21 @@ private static void logErr(String message) { public static void main (String argv[]) { - for (int i=0; i classesbyname001a: debugee started!"); // informing debuger of readyness ArgumentHandler argHandler = new ArgumentHandler(argv); IOPipe pipe = argHandler.createDebugeeIOPipe(); pipe.println("ready"); - int exitCode = PASSED; for (int i = 0; ; i++) { String instruction; - log1("waiting for an instruction from the debuger ..."); + log.display("**> classesbyname001a: waiting for an instruction from the debuger ..."); instruction = pipe.readln(); if (instruction.equals("quit")) { - log1("'quit' recieved"); + log.display("**> classesbyname001a: 'quit' recieved"); break ; } @@ -122,15 +103,12 @@ public static void main (String argv[]) { pipe.println("checkready"); break ; - // not a fully qualified name case 7: pipe.println("checkready"); break ; - - //------------------------------------------------- standard end section default: @@ -139,8 +117,8 @@ public static void main (String argv[]) { } } else { - logErr("unexpected instruction: " + instruction); - logErr("FAILED!"); + log.complain("classesbyname001a: unexpected instruction: " + instruction); + log.complain("classesbyname001a: FAILED!"); exitCode = 2; break ; } @@ -150,7 +128,6 @@ public static void main (String argv[]) { } } - class Class1ForCheck { // static fields diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java index e40906c299ae..36eb44df87a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,10 @@ public class setvalues001 { static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + // tested final class name and signature constants + static final String TESTED_FINAL_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedFinalClass"; + static final String TESTED_FINAL_CLASS_SIGNATURE = "L" + TESTED_FINAL_CLASS_NAME.replace('.', '/') + ";"; + // target values class name and signature constants static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; @@ -147,7 +151,7 @@ public int runIt(String argv[], PrintStream out) { log.display("Getting values of the static fields"); JDWP.Value targetValues[] = queryClassFieldValues(targetValuesClassID, targetValuesFieldIDs); - log.display(" got values: " + targetValues.length); + log.display(" got target values: " + targetValues.length); if (targetValues.length != count) { throw new Failure("Unexpected number of static fields values received: " + targetValues.length + "(expected: " + count + ")"); @@ -157,7 +161,7 @@ public int runIt(String argv[], PrintStream out) { log.display("Getting tested classID by signature:\n" + " " + TESTED_CLASS_SIGNATURE); long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); - log.display(" got classID: " + testedClassID); + log.display(" got tested classID: " + testedClassID); // query debugee for fieldIDs of tested class static fields log.display("Getting fieldIDs for static fields of the tested class"); @@ -168,14 +172,32 @@ public int runIt(String argv[], PrintStream out) { + testedFieldIDs.length + "(expected: " + count + ")"); } - // perform testing JDWP command - log.display("\n>>> Testing JDWP command \n"); + // query debugee for classID of the tested final class + log.display("Getting tested final classID by signature:\n" + + " " + TESTED_FINAL_CLASS_SIGNATURE); + long testedFinalClassID = debugee.getReferenceTypeID(TESTED_FINAL_CLASS_SIGNATURE); + log.display(" got tested final classID: " + testedFinalClassID); + + // query debugee for fieldIDs of tested final class static fields + log.display("Getting fieldIDs for static fields of the tested final class"); + long testedFinalFieldIDs[] = queryClassFieldIDs(testedFinalClassID); + log.display(" got fields: " + testedFinalFieldIDs.length); + if (testedFinalFieldIDs.length != count) { + throw new Failure("Unexpected number of static fields of tested final class received: " + + testedFinalFieldIDs.length + "(expected: " + count + ")"); + } + + log.display("\n>>> Testing JDWP ClassType.SetValues command on tested class\n"); testCommand(testedClassID, testedFieldIDs, targetValues); - // check confirmation from debuggee that values have been set properly - log.display("\n>>> Checking that the values have been set properly \n"); + log.display("\n>>> Checking with the debuggee that the values have been set properly\n"); checkValuesChanged(); + log.display("\n>>> Testing JDWP ClassType.SetValues command on tested final class\n"); + testCommand(testedFinalClassID, testedFinalFieldIDs, targetValues); + + log.display("\n>>> Checking with JDWP ClassType.GetValues that the values have been set properly \n"); + checkJDWPValuesChanged(testedFinalClassID, testedFinalFieldIDs, targetValues); } finally { // quit debugee log.display("\n>>> Finishing test \n"); @@ -399,7 +421,7 @@ void testCommand(long classID, long fieldIDs[], JDWP.Value values[]) { } /** - * Check confiramtion from debuggee that values are changed. + * Check confirmation from debuggee that values are changed. */ void checkValuesChanged() { // send debugee signal RUN @@ -426,4 +448,39 @@ void checkValuesChanged() { } } + /** + * Check confirmation using JDWP ClassType.GetValues that the values are changed. + */ + void checkJDWPValuesChanged(long testedClassID, long testedFieldIDs[], + JDWP.Value targetValues[]) { + // verify that JDWP ClassType.GetValues returns the expected values + int count = targetValues.length; + log.display("\n>>> Getting field values using JDWP ClassType.GetValues \n"); + JDWP.Value[] actualValues = queryClassFieldValues(testedClassID, testedFieldIDs); + log.display(" got actual values: " + actualValues.length); + if (actualValues.length != count) { + throw new Failure("Unexpected number of static field values received: " + + actualValues.length + "(expected: " + count + ")"); + } + for (int i = 0; i < count; i++) { + log.display(" field #" + i +":"); + log.display(" fieldID: " + testedFieldIDs[i]); + + JDWP.Value actualValue = actualValues[i]; + JDWP.Value targetValue = targetValues[i]; + JDWP.UntaggedValue untaggedActualValue = + new JDWP.UntaggedValue(actualValue.getValue()); + JDWP.UntaggedValue untaggedTargetValue = + new JDWP.UntaggedValue(targetValue.getValue()); + log.display(" untaggedActualValue: " + untaggedActualValue.getValue()); + log.display(" untaggedTargetValue: " + untaggedTargetValue.getValue()); + if (!untaggedActualValue.getValue().equals(untaggedTargetValue.getValue())) { + log.complain("JDWP found a static field that was not correctly set"); + success = false; + } + } + if (success) { + log.display("Verfied using JDWP ClassType.GetValues that all static fields values have been correctly set"); + } + } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java index ff3eb2789d4b..26c9fa647d0b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,7 @@ public int runIt(String args[], PrintStream out) { OriginalValuesClass original = new OriginalValuesClass(); TargetValuesClass target = new TargetValuesClass(); TestedClass tested = new TestedClass(); + TestedFinalClass testedFinal = new TestedFinalClass(); // send debugger signal READY log.display("Sending signal to debugger: " + setvalues001.READY); @@ -279,7 +280,7 @@ static boolean checkValues() { } */ - // check taht no any changed value differs from target + // check that none of the changed values differs from target if (different > 0) { log.complain("Values of " + different + " fields have not been set correctly"); return false; @@ -303,7 +304,7 @@ public static class OriginalValuesClass { static final Object objectValue = new OriginalValuesClass(); } - // class with the original values of static fields + // class with the target values of static fields public static class TargetValuesClass { static final boolean booleanValue = false; static final byte byteValue = (byte)0x0F; @@ -331,4 +332,18 @@ public static class TestedClass { static Object objectValue = OriginalValuesClass.objectValue; } + // tested class with own static final fields values + public static class TestedFinalClass { + private static final boolean booleanValue = OriginalValuesClass.booleanValue; + private static final byte byteValue = OriginalValuesClass.byteValue; + protected static final char charValue = OriginalValuesClass.charValue; + protected static final int intValue = OriginalValuesClass.intValue; + public static final short shortValue = OriginalValuesClass.shortValue; + public static final long longValue = OriginalValuesClass.longValue; + static final float floatValue = OriginalValuesClass.floatValue; + static final double doubleValue = OriginalValuesClass.doubleValue; + static final String stringValue = OriginalValuesClass.stringValue; + static final Object objectValue = OriginalValuesClass.objectValue; + } + } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java index 537c75014af1..342a3beeb010 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.BREAKPOINT; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,7 +37,7 @@ */ public class breakpoint001a { - static final int BREAKPOINT_LINE = 91; + static final int BREAKPOINT_LINE = 92; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -53,7 +54,7 @@ public int runIt(String args[], PrintStream out) { // create tested thread log.display("Creating tested thread"); - TestedClass.thread = new TestedClass(breakpoint001.TESTED_THREAD_NAME); + TestedClass.thread = new TestedClass(breakpoint001.TESTED_THREAD_NAME).getThread(); log.display(" ... thread created"); // start tested thread @@ -77,8 +78,8 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { - public static volatile TestedClass thread = null; + public static class TestedClass extends ThreadWrapper { + public static volatile Thread thread = null; public TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java index eba8fe6e1dec..1422b149ff01 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.EXCEPTION; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,9 +37,9 @@ */ public class exception001a { - static final int BREAKPOINT_LINE = 102; - static final int EXCEPTION_THROW_LINE = 114; - static final int EXCEPTION_CATCH_LINE = 121; // line number was changed due to 4740123 + static final int BREAKPOINT_LINE = 103; + static final int EXCEPTION_THROW_LINE = 115; + static final int EXCEPTION_CATCH_LINE = 122; // line number was changed due to 4740123 static ArgumentHandler argumentHandler = null; static Log log = null; @@ -84,7 +85,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { // static field with tested exception object public static volatile TestedExceptionClass exception = null; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java index f027416d975f..c029973b990f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.FIELD_ACCESS; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class fldaccess001a { - static final int BREAKPOINT_LINE = 114; - static final int FIELD_ACCESS_LINE = 125; + static final int BREAKPOINT_LINE = 115; + static final int FIELD_ACCESS_LINE = 126; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -82,7 +83,7 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { public TestedThreadClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java index 89ac3b882796..c78b61e72c18 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.FIELD_MODIFICATION; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class fldmodification001a { - static final int BREAKPOINT_LINE = 114; - static final int FIELD_MODIFICATION_LINE = 126; + static final int BREAKPOINT_LINE = 115; + static final int FIELD_MODIFICATION_LINE = 127; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -82,7 +83,7 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { public TestedThreadClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java index c231340f5325..49db5c5af99e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.METHOD_ENTRY; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class methentry001a { - static final int BREAKPOINT_LINE = 91; - static final int METHOD_ENTRY_LINE = 103; + static final int BREAKPOINT_LINE = 92; + static final int METHOD_ENTRY_LINE = 104; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -78,7 +79,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { public TestedClass(String name) { super(name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java index 4cd940f15d8e..469a0d9bd960 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.METHOD_EXIT; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class methexit001a { - static final int BREAKPOINT_LINE = 91; - static final int METHOD_EXIT_LINE = 105; + static final int BREAKPOINT_LINE = 92; + static final int METHOD_EXIT_LINE = 106; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -78,7 +79,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { public TestedClass(String name) { super(name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java index cf2937c5266e..5a87fc4431aa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.SINGLE_STEP; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class singlestep001a { - static final int BREAKPOINT_LINE = 91; - static final int SINGLE_STEP_LINE = 94; + static final int BREAKPOINT_LINE = 92; + static final int SINGLE_STEP_LINE = 95; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -78,7 +79,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { public TestedClass(String name) { super(name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java index b79a8b0b322b..17e01ba8def1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.SINGLE_STEP; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class singlestep002a { - static final int BREAKPOINT_LINE = 91; - static final int SINGLE_STEP_LINE = 101; + static final int BREAKPOINT_LINE = 92; + static final int SINGLE_STEP_LINE = 102; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -78,7 +79,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { public TestedClass(String name) { super(name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java index 164db266ce7b..617c51e4e897 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.SINGLE_STEP; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,8 +37,8 @@ */ public class singlestep003a { - static final int BREAKPOINT_LINE = 101; - static final int SINGLE_STEP_LINE = 92; + static final int BREAKPOINT_LINE = 102; + static final int SINGLE_STEP_LINE = 93; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -78,7 +79,7 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { public TestedClass(String name) { super(name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java index 140ae1257f62..1f092ea052f9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.THREAD_DEATH; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,7 +37,7 @@ */ public class thrdeath001a { - static final int BREAKPOINT_LINE = 93; + static final int BREAKPOINT_LINE = 94; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -53,7 +54,7 @@ public int runIt(String args[], PrintStream out) { // create tested thread log.display("Creating tested thread"); - TestedClass.thread = new TestedClass(thrdeath001.TESTED_THREAD_NAME); + TestedClass.thread = new TestedClass(thrdeath001.TESTED_THREAD_NAME).getThread(); log.display(" ... thread created"); // reach breakpoint @@ -80,8 +81,8 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { - public static volatile TestedClass thread = null; + public static class TestedClass extends ThreadWrapper { + public static volatile Thread thread = null; public TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java index 674a49d942b9..c5d44df6924c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.Event.THREAD_START; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -36,7 +37,7 @@ */ public class thrstart001a { - static final int BREAKPOINT_LINE = 93; + static final int BREAKPOINT_LINE = 94; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -53,7 +54,7 @@ public int runIt(String args[], PrintStream out) { // create tested thread log.display("Creating tested thread"); - TestedClass.thread = new TestedClass(thrstart001.TESTED_THREAD_NAME); + TestedClass.thread = new TestedClass(thrstart001.TESTED_THREAD_NAME).getThread(); log.display(" ... thread created"); // reach breakpoint @@ -80,8 +81,8 @@ public int runIt(String args[], PrintStream out) { } // tested class - public static class TestedClass extends Thread { - public static volatile TestedClass thread = null; + public static class TestedClass extends ThreadWrapper { + public static volatile Thread thread = null; public TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java index fa0386cfa5db..b7e528be32e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,6 +215,9 @@ public TestedClass() { } // TestedClass class // thread which will owns monitor of the tested object + // Note: the monitor threads must extend Thread, not ThreadWrapper. JDWP + // ObjectReference.MonitorInfo reports no owner and no waiters when virtual + // threads own or wait on the monitor. See JDK-8382276. public static class MonitorOwnerThread extends Thread { public Object ready = new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java index d9a7622ea042..6cfdaab2923a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,16 +67,21 @@ public class setvalues001 { static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + // tested final class name and signature constants + static final String TESTED_FINAL_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedFinalClass"; + static final String TESTED_FINAL_CLASS_SIGNATURE = "L" + TESTED_FINAL_CLASS_NAME.replace('.', '/') + ";"; + // target values class name and signature constants static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; - // name and siagnature of a class with static field with the tested object value + // name and signature of a class with static field with the tested object value static final String OBJECT_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "ObjectClass"; static final String OBJECT_CLASS_SIGNATURE = "L" + OBJECT_CLASS_NAME.replace('.', '/') + ";"; - // name of the static field in the tested class with the tested object value + // name of the static field in ObjectClass with the tested object values static final String OBJECT_FIELD_NAME = setvalues001a.OBJECT_FIELD_NAME; + static final String FINAL_OBJECT_FIELD_NAME = setvalues001a.FINAL_OBJECT_FIELD_NAME; // usual scaffold objects ArgumentHandler argumentHandler = null; @@ -154,7 +159,7 @@ public int runIt(String argv[], PrintStream out) { log.display("Getting values of the static fields"); JDWP.Value targetValues[] = queryClassFieldValues(targetValuesClassID, targetValuesFieldIDs); - log.display(" got values: " + targetValues.length); + log.display(" got target values: " + targetValues.length); if (targetValues.length != count) { throw new Failure("Unexpected number of static fields values received: " + targetValues.length + "(expected: " + count + ")"); @@ -164,7 +169,7 @@ public int runIt(String argv[], PrintStream out) { log.display("Getting tested classID by signature:\n" + " " + TESTED_CLASS_SIGNATURE); long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); - log.display(" got classID: " + testedClassID); + log.display(" got tested classID: " + testedClassID); // query debugee for fieldIDs of tested class fields log.display("Getting fieldIDs for tested fields of the tested class"); @@ -175,6 +180,21 @@ public int runIt(String argv[], PrintStream out) { + testedFieldIDs.length + "(expected: " + count + ")"); } + // query debugee for classID of the tested final class + log.display("Getting tested final classID by signature:\n" + + " " + TESTED_FINAL_CLASS_SIGNATURE); + long testedFinalClassID = debugee.getReferenceTypeID(TESTED_FINAL_CLASS_SIGNATURE); + log.display(" got tested final classID: " + testedFinalClassID); + + // query debugee for fieldIDs of tested final class fields + log.display("Getting fieldIDs for tested fields of the tested final class"); + long testedFinalFieldIDs[] = queryClassFieldIDs(testedFinalClassID); + log.display(" got fields: " + testedFinalFieldIDs.length); + if (testedFinalFieldIDs.length != count) { + throw new Failure("Unexpected number of fields of tested final class received: " + + testedFinalFieldIDs.length + "(expected: " + count + ")"); + } + // query debugee for classID of the object class log.display("Getting object classID by signature:\n" + " " + OBJECT_CLASS_SIGNATURE); @@ -188,14 +208,24 @@ public int runIt(String argv[], PrintStream out) { OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); log.display(" got objectID: " + objectID); - // perform testing JDWP command - log.display("\n>>> Testing JDWP command \n"); + // query debuggee for finalObjectID value from static field + log.display("Getting finalObjectID value from static field: " + + FINAL_OBJECT_FIELD_NAME); + long finalObjectID = queryObjectID(classID, + FINAL_OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got finalObjectID: " + finalObjectID); + + log.display("\n>>> Testing JDWP ObjectReference.SetValues command on tested class\n"); testCommand(objectID, testedFieldIDs, targetValues); - // check confirmation from debuggee that values have been set properly - log.display("\n>>> Checking that the values have been set properly \n"); + log.display("\n>>> Checking with the debuggee that the values have been set properly\n"); checkValuesChanged(); + log.display("\n>>> Testing JDWP ObjectReference.SetValues command on tested final class\n"); + testCommand(finalObjectID, testedFinalFieldIDs, targetValues); + + log.display("\n>>> Checking with JDWP ObjectReference.GetValues that the values have been set properly\n"); + checkJDWPValuesChanged(finalObjectID, testedFinalFieldIDs, targetValues); } finally { // quit debugee log.display("\n>>> Finishing test \n"); @@ -344,6 +374,43 @@ JDWP.Value[] queryClassFieldValues(long classID, long fieldIDs[]) { } } + /** + * Query debugee for values of the object fields. + */ + JDWP.Value[] queryObjectFieldValues(long objectID, long fieldIDs[]) { + // compose ReferenceType.Fields command packet + int count = fieldIDs.length; + CommandPacket command = new CommandPacket(JDWP.Command.ObjectReference.GetValues); + command.addObjectID(objectID); + command.addInt(count); + for (int i = 0; i < count; i++) { + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract values from the reply packet + try { + reply.resetPosition(); + + int valuesCount = reply.getInt(); + JDWP.Value values[] = new JDWP.Value[valuesCount]; + for (int i = 0; i < valuesCount; i++ ) { + JDWP.Value value = reply.getValue(); + values[i] = value; + } + return values; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.GetValues command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting fields values for objectID: " + objectID); + } + } + /** * Query debuggee for objectID value of static class field. */ @@ -440,7 +507,7 @@ void testCommand(long objectID, long fieldIDs[], JDWP.Value values[]) { } /** - * Check confiramtion from debuggee that values are changed. + * Check confirmation from debuggee that values are changed. */ void checkValuesChanged() { // send debugee signal RUN @@ -467,4 +534,39 @@ void checkValuesChanged() { } } + /** + * Check confirmation using JDWP ObjectReference.GetValues that the values are changed. + */ + void checkJDWPValuesChanged(long testedObjectID, long testedFieldIDs[], + JDWP.Value targetValues[]) { + // verify that JDWP ObjectReference.GetValues returns the expected values + int count = targetValues.length; + log.display("\n>>> Getting field values using JDWP ObjectReference.GetValues \n"); + JDWP.Value[] actualValues = queryObjectFieldValues(testedObjectID, testedFieldIDs); + log.display(" got actual values: " + actualValues.length); + if (actualValues.length != count) { + throw new Failure("Unexpected number of field values received: " + + actualValues.length + "(expected: " + count + ")"); + } + for (int i = 0; i < count; i++) { + log.display(" field #" + i +":"); + log.display(" fieldID: " + testedFieldIDs[i]); + + JDWP.Value actualValue = actualValues[i]; + JDWP.Value targetValue = targetValues[i]; + JDWP.UntaggedValue untaggedActualValue = + new JDWP.UntaggedValue(actualValue.getValue()); + JDWP.UntaggedValue untaggedTargetValue = + new JDWP.UntaggedValue(targetValue.getValue()); + log.display(" untaggedActualValue: " + untaggedActualValue.getValue()); + log.display(" untaggedTargetValue: " + untaggedTargetValue.getValue()); + if (!untaggedActualValue.getValue().equals(untaggedTargetValue.getValue())) { + log.complain("JDWP found a field that was not correctly set"); + success = false; + } + } + if (success) { + log.display("Verfied using JDWP ObjectReference.GetValues that all fields values have been correctly set"); + } + } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java index 1814034cd58a..15771a9fc45d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ public class setvalues001a { public static final String OBJECT_FIELD_NAME = "object"; + public static final String FINAL_OBJECT_FIELD_NAME = "finalObject"; static ArgumentHandler argumentHandler = null; static Log log = null; @@ -58,6 +59,7 @@ public int runIt(String args[], PrintStream out) { OriginalValuesClass original = new OriginalValuesClass(); TargetValuesClass target = new TargetValuesClass(); ObjectClass.object = new TestedClass(); + ObjectClass.finalObject = new TestedFinalClass(); // send debugger signal READY log.display("Sending signal to debugger: " + setvalues001.READY); @@ -284,7 +286,7 @@ static boolean checkValues(TestedClass object) { } */ - // check taht no any changed value differs from target + // check that none of the changed values differs from target if (different > 0) { log.complain("Values of " + different + " fields have not been set correctly"); return false; @@ -294,7 +296,7 @@ static boolean checkValues(TestedClass object) { return true; } - // class with the original values of static fields + // class with the original values of instance fields public static class OriginalValuesClass { static final boolean booleanValue = true; static final byte byteValue = (byte)0x01; @@ -308,7 +310,7 @@ public static class OriginalValuesClass { static final Object objectValue = new OriginalValuesClass(); } - // class with the original values of static fields + // class with the target values of instance fields public static class TargetValuesClass { static final boolean booleanValue = false; static final byte byteValue = (byte)0x0F; @@ -322,7 +324,7 @@ public static class TargetValuesClass { static final Object objectValue = new TargetValuesClass(); } - // tested class with own static fields values + // tested class with own instance fields values public static class TestedClass { private boolean booleanValue = OriginalValuesClass.booleanValue; private byte byteValue = OriginalValuesClass.byteValue; @@ -336,10 +338,25 @@ public static class TestedClass { Object objectValue = OriginalValuesClass.objectValue; } - // class with static field with the tested object + // tested class with own instance final fields values + public static class TestedFinalClass { + private final boolean booleanValue = OriginalValuesClass.booleanValue; + private final byte byteValue = OriginalValuesClass.byteValue; + protected final char charValue = OriginalValuesClass.charValue; + protected final int intValue = OriginalValuesClass.intValue; + public final short shortValue = OriginalValuesClass.shortValue; + public final long longValue = OriginalValuesClass.longValue; + final float floatValue = OriginalValuesClass.floatValue; + final double doubleValue = OriginalValuesClass.doubleValue; + final String stringValue = OriginalValuesClass.stringValue; + final Object objectValue = OriginalValuesClass.objectValue; + } + + // class with static fields with the tested objects public static class ObjectClass { - // static field with the tested object + // static fields with the tested objects public static TestedClass object = null; + public static TestedFinalClass finalObject = null; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java index d2bef481384c..66f2431e0e71 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.StackFrame.GetValues; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -74,7 +75,7 @@ public int runIt(String args[], PrintStream out) { log.display("Creating object of tested class"); TestedObjectClass.object = new TestedObjectClass(); log.display("Creating tested thread"); - TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME); + TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadReady) { @@ -123,7 +124,7 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { TestedThreadClass(String name) { super(name); @@ -144,7 +145,7 @@ public void run() { public static class TestedObjectClass { // field with the tested thread and object values - public static volatile TestedThreadClass thread = null; + public static volatile Thread thread = null; public static volatile TestedObjectClass object = null; public void testedMethod() { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java index 20bb707b14f6..cfe1a919bf93 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package nsk.jdwp.StackFrame.PopFrames; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -40,7 +41,7 @@ public class popframes001a { public static final String THREAD_NAME = "testedThread"; // line nunber for breakpoint - public static final int BREAKPOINT_LINE_NUMBER = 113; + public static final int BREAKPOINT_LINE_NUMBER = 114; // scaffold objects private static volatile ArgumentHandler argumentHandler = null; @@ -82,7 +83,7 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { // number of invokations of tested method public static volatile int invokations = 0; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java index 81c9a51b1cfc..27b4fd6d57f1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,6 +158,9 @@ public int runIt(String args[], PrintStream out) { } // tested thread class + // Note: TestedThreadClass must extend Thread, not ThreadWrapper. JDWP + // StackFrame.SetValues returns OPAQUE_FRAME for a virtual thread suspended + // with ThreadReference.Suspend rather than at an event. See JDK-8382276. public static class TestedThreadClass extends Thread { public TestedThreadClass(String name) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java index 42bb065994bc..81662743780f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.StackFrame.ThisObject; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -73,7 +74,7 @@ public int runIt(String args[], PrintStream out) { log.display("Creating object of tested class"); TestedObjectClass.object = new TestedObjectClass(); log.display("Creating tested thread"); - TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME); + TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadReady) { @@ -122,7 +123,7 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedThreadClass extends Thread { + public static class TestedThreadClass extends ThreadWrapper { TestedThreadClass(String name) { super(name); @@ -144,7 +145,7 @@ public void run() { public static class TestedObjectClass { // field with the tested thread and object values - public static volatile TestedThreadClass thread = null; + public static volatile Thread thread = null; public static volatile TestedObjectClass object = null; public void testedMethod(int foo) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java index 1f20c1c70414..ccd9f7d52080 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.CurrentContendedMonitor; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -69,7 +70,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarting) { @@ -84,8 +85,8 @@ public int runIt(String args[], PrintStream out) { } // ensure that tested thread is waiting for monitor object - synchronized (TestedClass.thread.monitor) { - TestedClass.thread.monitor.notifyAll(); + synchronized (TestedClass.monitor) { + TestedClass.monitor.notifyAll(); // send debugger signal READY log.display("Sending signal to debugger: " + curcontmonitor001.READY); @@ -112,10 +113,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; // field with monitor object which thread will infinitively wait for public static volatile Object monitor = new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java index eba135fe2b45..530c2f1f0d7c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,9 @@ public int runIt(String args[], PrintStream out) { } // tested thread class + // Note: TestedClass must extend Thread, not ThreadWrapper. This test + // asserts an exact frame count, which the wrapper's extra frames change. + // See JDK-8382276. public static class TestedClass extends Thread { // field with the tested Thread value diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java index d106259c431f..951d40a9bf12 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Frames; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -70,7 +71,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadReady) { @@ -108,10 +109,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; int frames = 0; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java index 7677411b7d84..000b91a929d2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Interrupt; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarting) { @@ -139,10 +140,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java index de88acecf519..0cc160a56699 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Name; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarted) { @@ -104,10 +105,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java index 0f929bcdac44..0be2457496bc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.OwnedMonitors; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -68,7 +69,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadReady) { @@ -106,10 +107,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; // field with object whose monitor the tested thread owns public static Object ownedMonitor = new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java index 689e7693021c..9517ec28285c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Resume; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarted) { @@ -104,10 +105,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java index 1429a7e4a75a..c3589bcf326e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Status; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarted) { @@ -104,10 +105,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java index f046041276ca..30f2d41eaaaa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,6 +144,9 @@ public int runIt(String args[], PrintStream out) { } // tested thread class + // Note: TestedClass must extend Thread, not ThreadWrapper. JDWP + // ThreadReference.Stop returns THREAD_NOT_SUSPENDED for a virtual thread + // that is not suspended at an event. See JDK-8382276. public static class TestedClass extends Thread { // field with the tested Thread value diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java index eced97136d62..fd3da5283915 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.Suspend; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarted) { @@ -104,10 +105,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java index 5c6d77b1b8a3..5a9b4d025ebd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.jdwp.ThreadReference.SuspendCount; +import jdk.test.lib.thread.ThreadWrapper; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdwp.*; @@ -66,7 +67,7 @@ public int runIt(String args[], PrintStream out) { // load tested class and create tested thread log.display("Creating object of tested class"); - TestedClass.thread = new TestedClass(THREAD_NAME); + TestedClass.thread = new TestedClass(THREAD_NAME).getThread(); // start the thread and wait for notification from it synchronized (threadStarted) { @@ -104,10 +105,10 @@ public int runIt(String args[], PrintStream out) { } // tested thread class - public static class TestedClass extends Thread { + public static class TestedClass extends ThreadWrapper { // field with the tested Thread value - public static volatile TestedClass thread = null; + public static volatile Thread thread = null; TestedClass(String name) { super(name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.java index 9d121b9a94f7..5ee794211f32 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -653,21 +653,9 @@ public SleepingThread(ThreadController controller, String name, Log log, Threads this.threadsGroupLocks = threadsGroupLocks; - expectedLength += 4; + expectedLength++; expectedMethods.add(Thread.class.getName() + ".sleep"); - expectedMethods.add(Thread.class.getName() + ".sleepNanos"); - expectedMethods.add(Thread.class.getName() + ".sleepNanos0"); - expectedMethods.add(Thread.class.getName() + ".beforeSleep"); - expectedMethods.add(Thread.class.getName() + ".afterSleep"); - expectedMethods.add(Thread.class.getName() + ".currentCarrierThread"); - expectedMethods.add(Thread.class.getName() + ".currentThread"); - // jdk.internal.event.ThreadSleepEvent not accessible - expectedMethods.add("java.lang.Object."); - expectedMethods.add("jdk.internal.event.Event."); - expectedMethods.add("jdk.internal.event.ThreadSleepEvent."); - expectedMethods.add("jdk.internal.event.ThreadSleepEvent."); - expectedMethods.add("jdk.internal.event.ThreadSleepEvent.isEnabled"); expectedMethods.add(SleepingThread.class.getName() + ".run"); switch (controller.invocationType) { @@ -698,6 +686,27 @@ public boolean checkState(Thread.State state) { return state == Thread.State.TIMED_WAITING; } + public boolean checkStackTrace(StackTraceElement[] elements) { + if (elements.length == 0) { + // ThreadMXBean.getThreadInfo(long) and getThreadInfo(long[]) return + // ThreadInfo without a stack trace, so there is nothing to check. + return true; + } + // Only the java.lang.Thread.sleep entry frame is required here. + // Frames above it are implementation details of sleep that change + // between releases, so they are not checked. + for (int i = elements.length - 1; i >= 0; i--) { + if (elements[i].getClassName().equals("java.lang.Thread") + && elements[i].getMethodName().equals("sleep")) { + // The frames below the sleep entry are the test's own stack and still get checked. + return super.checkStackTrace( + Arrays.copyOfRange(elements, i, elements.length)); + } + } + logger.complain("No java.lang.Thread.sleep frame in the stack trace"); + return false; + } + public void run() { try { switch (controller.invocationType) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/thread/SleepingThread.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/thread/SleepingThread.java index 217c2cdfdc82..300b660b89af 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/thread/SleepingThread.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/thread/SleepingThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package nsk.monitoring.share.thread; import nsk.share.log.Log; +import java.util.Arrays; import java.lang.management.ThreadInfo; import java.lang.management.MonitorInfo; import java.lang.management.LockInfo; @@ -36,16 +37,6 @@ public class SleepingThread extends RecursiveMonitoringThread { private Object readyLock = new Object(); private static final String[] expectedMethods = { "java.lang.Thread.sleep", - "java.lang.Thread.sleepNanos", - "java.lang.Thread.sleepNanos0", - "java.lang.Thread.beforeSleep", - "java.lang.Thread.afterSleep", - "java.util.concurrent.TimeUnit.toNanos", - "java.lang.Object.", - "jdk.internal.event.Event.", - "jdk.internal.event.ThreadSleepEvent.", - "jdk.internal.event.ThreadSleepEvent.", - "jdk.internal.event.ThreadSleepEvent.isEnabled", "nsk.monitoring.share.thread.SleepingThread.runInside" }; @@ -99,6 +90,26 @@ protected void runInside() { } } + protected boolean checkStackTrace(StackTraceElement[] elements) { + if (elements.length == 0) { + // ThreadMXBean.getThreadInfo(long) and getThreadInfo(long[]) return + // ThreadInfo without a stack trace, so there is nothing to check. + return true; + } + // Only the java.lang.Thread.sleep entry frame is required here. + // Frames above it are implementation details of sleep that change + // between releases, so they are not checked. + for (int i = elements.length - 1; i >= 0; i--) { + if (elements[i].getClassName().equals("java.lang.Thread") + && elements[i].getMethodName().equals("sleep")) { + // The frames below the sleep entry are the test's own stack and still get checked. + return super.checkStackTrace(Arrays.copyOfRange(elements, i, elements.length)); + } + } + log.info("No java.lang.Thread.sleep frame in stack trace for: " + this); + return false; + } + protected boolean isStackTraceElementExpected(StackTraceElement element) { return super.isStackTraceElementExpected(element) || checkStackTraceElement(element, expectedMethods); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java index 0700032f6a7c..74d54d8e31cd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ public class strace001 { private static int depth; private static int threadCount; private static String[] expectedTrace; - private static String[] expectedSystemTrace; private static ThreadMonitor monitor; private static ThreadController controller; @@ -138,23 +137,6 @@ public static int run(String[] argv, PrintStream out) { // Fill expectedTrace array according to the invocation type that is set in // test options private static boolean fillTrace() { - expectedSystemTrace = new String[]{ - "java.lang.Thread.sleep", - "java.lang.Thread.sleepNanos", - "java.lang.Thread.sleepNanos0", - "java.lang.Thread.beforeSleep", - "java.lang.Thread.afterSleep", - "java.lang.Thread.yield", - "java.lang.Thread.yield0", - "java.lang.Thread.currentCarrierThread", - "java.lang.Thread.currentThread", - "java.util.concurrent.TimeUnit.toNanos", - "jdk.internal.event.ThreadSleepEvent.", - "java.lang.Object.", - "jdk.internal.event.Event.", - "jdk.internal.event.ThreadSleepEvent.", - "jdk.internal.event.ThreadSleepEvent.isEnabled" - }; switch (controller.getInvocationType()) { case ThreadController.JAVA_TYPE: @@ -206,15 +188,29 @@ private static void printStackTrace(StackTraceElement[] elements) { // The method performs checks of the stack trace private static boolean checkTrace(StackTraceElement[] elements) { - int length = elements.length; - // The length of the trace must not be greater than - // expectedLength. Number of recursionJava() or - // recursionNative() methods must not be greater than depth, - // also one run() and one waitForSign(), plus whatever can be - // reached from Thread.yield or Thread.sleep. - int expectedLength = depth + 7; boolean result = true; + // Find the innermost frame that belongs to the test's own code. + // Any frames above it come from the implementation of Thread.sleep + // or Thread.yield, which changes between releases, so they are + // not checked. + int firstOwn = -1; + for (int i = 0; i < elements.length; i++) { + if (isTestFrame(elements[i])) { + firstOwn = i; + break; + } + } + if (firstOwn < 0) { + log.complain("No frames of " + THREAD_NAME + " in the stack trace"); + return false; + } + + // The number of recursionJava() or recursionNative() frames must not + // be greater than depth, plus one run() and one waitForSign(). + int length = elements.length - firstOwn; + int expectedLength = depth + expectedTrace.length; + // Check the length of the trace if (length > expectedLength) { log.complain("Length of the stack trace is " + length + ", but " @@ -223,14 +219,12 @@ private static boolean checkTrace(StackTraceElement[] elements) { } // Check each element of the snapshot - for (int i = 0; i < elements.length; i++) { + for (int i = firstOwn; i < elements.length; i++) { if (i == elements.length - 1) { - // The latest method of the snapshot must be RunningThread.run() if ( !checkLastElement(elements[i]) ) result = false; } else { - // getClassName() and getMethodName() must return correct values // for each element if ( !checkElement(i, elements[i]) ) @@ -240,6 +234,16 @@ private static boolean checkTrace(StackTraceElement[] elements) { return result; } + // The method checks whether the element belongs to the test's own code. + private static boolean isTestFrame(StackTraceElement element) { + String name = element.getClassName() + "." + element.getMethodName(); + for (int i = 0; i < expectedTrace.length; i++) { + if (expectedTrace[i].equals(name)) + return true; + } + return false; + } + // The method checks that StackTraceElement.getClassName() and // StackTraceElement.getMethodName() return expected values private static boolean checkElement(int n, StackTraceElement element) { @@ -251,11 +255,6 @@ private static boolean checkElement(int n, StackTraceElement element) { return true; } - // Implementation of sleep/wait/yield - for (int i = 0; i < expectedSystemTrace.length; i++) { - if (expectedSystemTrace[i].equals(name)) - return true; - } log.complain("Unexpected " + n + " element of the stack trace:\n\t" + name); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java index db24db8b9a75..b3190f404732 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,14 +31,6 @@ */ /* - The description is misleading. I looked at some old email, and the - goal is to stress the code that deals with displaced mark words, so - the description should be more like "Stress tests for displaced mark - words." In hotspot, each object has a mark word that stores several - things about the object including its hash code (if it has one) and - lock state. Most objects never have a hash code and are never locked, - so the mark word is empty. - Most of our garbage collectors use the mark word temporarily during GC to store a 'forwarding pointer.' It's not important what that is, but it means that objects that have a hash code or that are locked have to diff --git a/test/jdk/java/foreign/CallGeneratorHelper.java b/test/jdk/java/foreign/CallGeneratorHelper.java index 6fd32eac4109..1854d00c4a8f 100644 --- a/test/jdk/java/foreign/CallGeneratorHelper.java +++ b/test/jdk/java/foreign/CallGeneratorHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,10 @@ import java.util.stream.Stream; import jdk.internal.foreign.Utils; -import org.testng.annotations.*; +import org.junit.jupiter.api.TestInstance; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class CallGeneratorHelper extends NativeTestHelper { static final List STACK_PREFIX_LAYOUTS = Stream.concat( @@ -151,7 +153,6 @@ static void generateTest(int i, Stack combo, Z[] elems, List> res } } - @DataProvider(name = "functions") public static Object[][] functions() { int functions = 0; List downcalls = new ArrayList<>(); @@ -209,7 +210,7 @@ private static PrintStream printStream(String first) throws IOException { // This can be used to generate the test implementation. // From the test/jdk/java/foreign directory, run this class using: - // java -cp \lib\testng-7.3.0.jar --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED ./CallGeneratorHelper.java + // java -cp /lib/junit-platform-console-standalone-1.14.2.jar --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED ./CallGeneratorHelper.java // Copyright header has to be added manually, and on Windows line endings have to be changed from \r\n to just \n public static void main(String[] args) throws IOException { try (PrintStream shared = printStream("shared.h"); diff --git a/test/jdk/java/foreign/CompositeLookupTest.java b/test/jdk/java/foreign/CompositeLookupTest.java index 1cc0b35950d3..a3c34ea9e8e7 100644 --- a/test/jdk/java/foreign/CompositeLookupTest.java +++ b/test/jdk/java/foreign/CompositeLookupTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,36 +21,39 @@ * questions. */ -import org.testng.annotations.Test; import java.lang.foreign.*; import java.util.List; import java.util.Optional; import java.util.Set; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test - * @run testng CompositeLookupTest + * @run junit CompositeLookupTest */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class CompositeLookupTest { - @Test(dataProvider = "testCases") + @ParameterizedTest + @MethodSource("testCases") public void testLookups(SymbolLookup lookup, List results) { for (Result result : results) { switch (result) { case Success(String name, long expectedLookupId) -> { Optional symbol = lookup.find(name); assertTrue(symbol.isPresent()); - assertEquals(symbol.get().address(), expectedLookupId); + assertEquals(expectedLookupId, symbol.get().address()); } case Failure(String name) -> { Optional symbol = lookup.find(name); assertFalse(symbol.isPresent()); } + } } } @@ -76,7 +79,6 @@ sealed interface Result { } record Success(String name, long expectedLookupId) implements Result { } record Failure(String name) implements Result { } - @DataProvider(name = "testCases") public Object[][] testCases() { return new Object[][]{ { diff --git a/test/jdk/java/foreign/LibraryLookupTest.java b/test/jdk/java/foreign/LibraryLookupTest.java index ad2f02c5df3f..8c71c2286549 100644 --- a/test/jdk/java/foreign/LibraryLookupTest.java +++ b/test/jdk/java/foreign/LibraryLookupTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,6 @@ * questions. */ -import org.testng.annotations.Test; import java.io.IOException; import java.lang.foreign.*; @@ -37,11 +36,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; /* * @test id=specialized - * @run testng/othervm/native + * @run junit/othervm/native * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * --enable-native-access=ALL-UNNAMED * LibraryLookupTest @@ -49,7 +49,7 @@ /* * @test id=interpreted - * @run testng/othervm/native + * @run junit/othervm/native * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * --enable-native-access=ALL-UNNAMED * LibraryLookupTest @@ -73,19 +73,23 @@ void testLoadLibraryConfined() { } } - @Test(expectedExceptions = IllegalStateException.class) + @Test void testLoadLibraryConfinedClosed() { MemorySegment addr; try (Arena arena = Arena.ofConfined()) { addr = loadLibrary(arena); } - callFunc(addr); + assertThrows(IllegalStateException.class, () -> { + callFunc(addr); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testLoadLibraryBadName() { try (Arena arena = Arena.ofConfined()) { - SymbolLookup.libraryLookup(LIB_PATH.toString() + "\u0000", arena); + assertThrows(IllegalArgumentException.class, () -> { + SymbolLookup.libraryLookup(LIB_PATH.toString() + "\u0000", arena); + }); } } @@ -99,7 +103,7 @@ void testLoadLibraryBadLookupName() { @Test void testLoadLibraryNonDefaultFileSystem() throws URISyntaxException, IOException { - try (FileSystem customFs = fsFromJarOfClass(org.testng.annotations.Test.class)) { + try (FileSystem customFs = fsFromJarOfClass(Test.class)) { try (Arena arena = Arena.ofConfined()) { Path p = customFs.getPath("."); try { @@ -131,7 +135,7 @@ private static FileSystem fsFromJarOfClass(Class clazz) throws URISyntaxExcep private static MemorySegment loadLibrary(Arena session) { SymbolLookup lib = SymbolLookup.libraryLookup(LIB_PATH, session); MemorySegment addr = lib.find("inc").get(); - assertEquals(addr.scope(), session.scope()); + assertEquals(session.scope(), addr.scope()); return addr; } @@ -149,14 +153,18 @@ private static void callFunc(MemorySegment addr) { static final int MAX_EXECUTOR_WAIT_SECONDS = 20; static final int NUM_ACCESSORS = Math.min(10, Runtime.getRuntime().availableProcessors()); - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testBadLibraryLookupName() { - SymbolLookup.libraryLookup("nonExistent", Arena.global()); + assertThrows(IllegalArgumentException.class, () -> { + SymbolLookup.libraryLookup("nonExistent", Arena.global()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testBadLibraryLookupPath() { - SymbolLookup.libraryLookup(Path.of("nonExistent"), Arena.global()); + assertThrows(IllegalArgumentException.class, () -> { + SymbolLookup.libraryLookup(Path.of("nonExistent"), Arena.global()); + }); } @Test diff --git a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java index c304a1390148..0ffd43ef6ddd 100644 --- a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java +++ b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * 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,15 +23,16 @@ /* * @test - * @run testng/othervm MemoryLayoutPrincipalTotalityTest + * @run junit/othervm MemoryLayoutPrincipalTotalityTest */ -import org.testng.annotations.*; import java.lang.foreign.*; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class MemoryLayoutPrincipalTotalityTest { @@ -43,7 +44,7 @@ public void testBasicTotality() { int v0 = switch (memoryLayout) { case MemoryLayout ml -> 1; }; - assertEquals(v0, 1); + assertEquals(1, v0); } @Test @@ -55,7 +56,7 @@ public void testMLRemovedTotality() { case SequenceLayout sl -> 0; // leaf case ValueLayout vl -> 1; }; - assertEquals(v1, 1); + assertEquals(1, v1); } @Test @@ -68,7 +69,7 @@ public void testMLGLRemovedTotality() { case StructLayout sl -> 0; // leaf case UnionLayout ul -> 0; // leaf }; - assertEquals(v2, 1); + assertEquals(1, v2); } @Test @@ -89,7 +90,7 @@ public void testMLGLVLRemovedTotality() { case OfLong ol -> 0; // leaf case OfShort os -> 0; // leaf }; - assertEquals(v3, 1); + assertEquals(1, v3); } @Test @@ -109,7 +110,7 @@ public void testMLVLRemovedTotality() { case OfLong ol -> 0; // leaf case OfShort os -> 0; // leaf }; - assertEquals(v4, 1); + assertEquals(1, v4); } private static MemoryLayout javaIntMemoryLayout() { diff --git a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java index ecfc4b0da38a..12f9b1451334 100644 --- a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java +++ b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * 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,16 +23,17 @@ /* * @test - * @run testng/othervm MemoryLayoutTypeRetentionTest + * @run junit/othervm MemoryLayoutTypeRetentionTest */ -import org.testng.annotations.*; import java.lang.foreign.*; import java.nio.ByteOrder; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class MemoryLayoutTypeRetentionTest { @@ -144,12 +145,12 @@ public void testAddressLayout() { .withoutTargetLayout() .withOrder(BYTE_ORDER); check(v); - assertEquals(v.order(), BYTE_ORDER); + assertEquals(BYTE_ORDER, v.order()); assertFalse(v.targetLayout().isPresent()); AddressLayout v2 = v.withTargetLayout(JAVA_INT); assertTrue(v2.targetLayout().isPresent()); - assertEquals(v2.targetLayout().get(), JAVA_INT); + assertEquals(JAVA_INT, v2.targetLayout().get()); assertTrue(v2.withoutTargetLayout().targetLayout().isEmpty()); } @@ -197,15 +198,15 @@ public void testUnionLayout() { public void check(ValueLayout v) { check((MemoryLayout) v); - assertEquals(v.order(), BYTE_ORDER); + assertEquals(BYTE_ORDER, v.order()); } public void check(MemoryLayout v) { // Check name properties - assertEquals(v.name().orElseThrow(), NAME); + assertEquals(NAME, v.name().orElseThrow()); assertTrue(v.withoutName().name().isEmpty()); - assertEquals(v.byteAlignment(), BYTE_ALIGNMENT); + assertEquals(BYTE_ALIGNMENT, v.byteAlignment()); } } diff --git a/test/jdk/java/foreign/SafeFunctionAccessTest.java b/test/jdk/java/foreign/SafeFunctionAccessTest.java index 658a0bfc7848..23ca75c3e2ec 100644 --- a/test/jdk/java/foreign/SafeFunctionAccessTest.java +++ b/test/jdk/java/foreign/SafeFunctionAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test id=specialized - * @run testng/othervm/native + * @run junit/othervm/native * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * --enable-native-access=ALL-UNNAMED * SafeFunctionAccessTest @@ -31,7 +31,7 @@ /* * @test id=interpreted - * @run testng/othervm/native + * @run junit/othervm/native * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * --enable-native-access=ALL-UNNAMED * SafeFunctionAccessTest @@ -49,9 +49,8 @@ import java.util.stream.Stream; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class SafeFunctionAccessTest extends NativeTestHelper { static { @@ -62,18 +61,18 @@ public class SafeFunctionAccessTest extends NativeTestHelper { C_INT, C_INT ); - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testClosedStruct() throws Throwable { MemorySegment segment; try (Arena arena = Arena.ofConfined()) { segment = arena.allocate(POINT); - } - assertFalse(segment.scope().isAlive()); + } assertFalse(segment.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("struct_func"), FunctionDescriptor.ofVoid(POINT)); - - handle.invokeExact(segment); + assertThrows(IllegalStateException.class, () -> { + handle.invokeExact(segment); + }); } @Test @@ -119,19 +118,19 @@ static Allocation of(MemoryLayout layout) { } } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testClosedUpcall() throws Throwable { MemorySegment upcall; try (Arena arena = Arena.ofConfined()) { MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), arena); - } - assertFalse(upcall.scope().isAlive()); + } assertFalse(upcall.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func"), FunctionDescriptor.ofVoid(C_POINTER)); - - handle.invokeExact(upcall); + assertThrows(IllegalStateException.class, () -> { + handle.invokeExact(upcall); + }); } static void dummy() { } diff --git a/test/jdk/java/foreign/Test4BAlignedDouble.java b/test/jdk/java/foreign/Test4BAlignedDouble.java index ce3bf6c5f2f8..958257e8c459 100644 --- a/test/jdk/java/foreign/Test4BAlignedDouble.java +++ b/test/jdk/java/foreign/Test4BAlignedDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,17 +26,18 @@ * @test * @summary Test passing of a structure which contains a double with 4 Byte alignment on AIX. * - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED Test4BAlignedDouble + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED Test4BAlignedDouble */ import java.lang.foreign.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.*; +import org.junit.jupiter.api.Test; + public class Test4BAlignedDouble { static { @@ -82,7 +83,7 @@ public class Test4BAlignedDouble { FunctionDescriptor.of(platform_S_IDFLayout, ADDRESS, platform_S_IDFLayout)); @Test - public static void testDowncall() { + public void testDowncall() { int p0 = 0; double p1 = 0.0d; float p2 = 0.0f; @@ -113,7 +114,7 @@ public static MemorySegment S_IDF_fun(MemorySegment p) { } @Test - public static void testUpcall() { + public void testUpcall() { int p0 = 0; double p1 = 0.0d; float p2 = 0.0f; diff --git a/test/jdk/java/foreign/TestAccessModes.java b/test/jdk/java/foreign/TestAccessModes.java index e54d4f1ae9ed..9bce17d679ed 100644 --- a/test/jdk/java/foreign/TestAccessModes.java +++ b/test/jdk/java/foreign/TestAccessModes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * 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,10 @@ /* * @test - * @run testng/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes - * @run testng/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes - * @run testng/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes - * @run testng/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes + * @run junit/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes + * @run junit/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes + * @run junit/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes + * @run junit/othervm/timeout=480 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes */ import java.lang.foreign.*; @@ -40,12 +40,15 @@ import java.util.List; import java.util.Set; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestAccessModes { - @Test(dataProvider = "segmentsAndLayoutsAndModes") + @ParameterizedTest + @MethodSource("segmentsAndLayoutsAndModes") public void testAccessModes(MemorySegment segment, MemoryLayout layout, AccessMode mode) throws Throwable { VarHandle varHandle = layout instanceof ValueLayout ? layout.varHandle() : @@ -61,7 +64,7 @@ public void testAccessModes(MemorySegment segment, MemoryLayout layout, AccessMo // access is unaligned assertTrue(segment.maxByteAlignment() < layout.byteAlignment()); } - assertEquals(varHandle.isAccessModeSupported(mode), compatible); + assertEquals(compatible, varHandle.isAccessModeSupported(mode)); } static ValueLayout accessLayout(MemoryLayout layout) { @@ -171,7 +174,6 @@ static MemorySegment[] segments() { }; } - @DataProvider(name = "segmentsAndLayoutsAndModes") static Object[][] segmentsAndLayoutsAndModes() { List segmentsAndLayouts = new ArrayList<>(); for (MemorySegment segment : segments()) { diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index ebbef0ffb6bc..9977329166dd 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,16 +24,15 @@ /* * @test - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles */ import java.lang.foreign.*; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -41,6 +40,8 @@ import java.lang.invoke.VarHandle; import java.util.List; +import org.junit.jupiter.api.Test; + public class TestAdaptVarHandles { static MethodHandle S2I; @@ -98,15 +99,15 @@ public void testFilterValue() throws Throwable { VarHandle i2SHandle = MethodHandles.filterValue(intHandle, S2I, I2S); i2SHandle.set(segment, 0L, "1"); String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); - assertEquals(oldValue, "1"); + assertEquals("1", oldValue); String value = (String)i2SHandle.get(segment, 0L); - assertEquals(value, "43"); + assertEquals("43", value); boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); - assertEquals(oldValue, "12"); + assertEquals("12", oldValue); value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); - assertEquals(value, "42"); + assertEquals("42", value); } @Test @@ -120,15 +121,15 @@ public void testFilterValueComposite() throws Throwable { i2SHandle = MethodHandles.insertCoordinates(i2SHandle, 2, "a", "b"); i2SHandle.set(segment, 0L, "1"); String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); - assertEquals(oldValue, "ab1"); + assertEquals("ab1", oldValue); String value = (String)i2SHandle.get(segment, 0L); - assertEquals(value, "ab43"); + assertEquals("ab43", value); boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); - assertEquals(oldValue, "ab12"); + assertEquals("ab12", oldValue); value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); - assertEquals(value, "ab42"); + assertEquals("ab42", value); } @Test @@ -140,72 +141,88 @@ public void testFilterValueLoose() throws Throwable { VarHandle i2SHandle = MethodHandles.filterValue(intHandle, O2I, I2O); i2SHandle.set(segment, 0L, "1"); String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); - assertEquals(oldValue, "1"); + assertEquals("1", oldValue); String value = (String)i2SHandle.get(segment, 0L); - assertEquals(value, "43"); + assertEquals("43", value); boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); - assertEquals(oldValue, "12"); + assertEquals("12", oldValue); value = (String)(Object)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); - assertEquals(value, "42"); + assertEquals("42", value); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCarrier() { - MethodHandles.filterValue(floatHandle, S2I, I2S); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(floatHandle, S2I, I2S); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterUnboxArity() { VarHandle floatHandle = ValueLayout.JAVA_INT.varHandle(); - MethodHandles.filterValue(floatHandle, S2I.bindTo(""), I2S); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(floatHandle, S2I.bindTo(""), I2S); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterBoxArity() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); - MethodHandles.filterValue(intHandle, S2I, I2S.bindTo(42)); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(intHandle, S2I, I2S.bindTo(42)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterBoxPrefixCoordinates() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); - MethodHandles.filterValue(intHandle, - MethodHandles.dropArguments(S2I, 1, int.class), - MethodHandles.dropArguments(I2S, 1, long.class)); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(intHandle, + MethodHandles.dropArguments(S2I, 1, int.class), + MethodHandles.dropArguments(I2S, 1, long.class)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterBoxException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); - MethodHandles.filterValue(intHandle, I2S, S2L_EX); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(intHandle, I2S, S2L_EX); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterUnboxException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); - MethodHandles.filterValue(intHandle, S2L_EX, I2S); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterValue(intHandle, S2L_EX, I2S); + }); } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testBadFilterBoxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I, I2S_EX); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT); vh.set(seg, 0L, "42"); - String x = (String) vh.get(seg, 0L); // should throw + assertThrows(IllegalStateException.class, () -> { + String x = (String) vh.get(seg, 0L); + }); } } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testBadFilterUnboxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I_EX, I2S); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT); - vh.set(seg, 0L, "42"); // should throw + assertThrows(IllegalStateException.class, () -> { + vh.set(seg, 0L, "42"); // should throw + }); } } @@ -217,40 +234,50 @@ public void testFilterCoordinates() throws Throwable { VarHandle intHandle_longIndex = MethodHandles.filterCoordinates(intHandleIndexed, 0, BASE_ADDR, S2L); intHandle_longIndex.set(segment, "0", 1); int oldValue = (int)intHandle_longIndex.getAndAdd(segment, "0", 42); - assertEquals(oldValue, 1); + assertEquals(1, oldValue); int value = (int)intHandle_longIndex.get(segment, "0"); - assertEquals(value, 43); + assertEquals(43, value); boolean swapped = (boolean)intHandle_longIndex.compareAndSet(segment, "0", 43, 12); assertTrue(swapped); oldValue = (int)intHandle_longIndex.compareAndExchange(segment, "0", 12, 42); - assertEquals(oldValue, 12); + assertEquals(12, oldValue); value = (int)intHandle_longIndex.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, "0"); - assertEquals(value, 42); + assertEquals(42, value); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCoordinatesNegativePos() { - MethodHandles.filterCoordinates(intHandle, -1, SUM_OFFSETS); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterCoordinates(intHandle, -1, SUM_OFFSETS); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCoordinatesPosTooBig() { - MethodHandles.filterCoordinates(intHandle, 1, SUM_OFFSETS); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterCoordinates(intHandle, 1, SUM_OFFSETS); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCoordinatesWrongFilterType() { - MethodHandles.filterCoordinates(intHandleIndexed, 1, S2I); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterCoordinates(intHandleIndexed, 1, S2I); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCoordinatesWrongFilterException() { - MethodHandles.filterCoordinates(intHandleIndexed, 1, S2L_EX); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterCoordinates(intHandleIndexed, 1, S2L_EX); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadFilterCoordinatesTooManyFilters() { - MethodHandles.filterCoordinates(intHandleIndexed, 1, S2L, S2L); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.filterCoordinates(intHandleIndexed, 1, S2L, S2L); + }); } @Test @@ -261,35 +288,43 @@ public void testInsertCoordinates() throws Throwable { VarHandle intHandle_longIndex = MethodHandles.insertCoordinates(intHandleIndexed, 0, segment, 0L); intHandle_longIndex.set(1); int oldValue = (int)intHandle_longIndex.getAndAdd(42); - assertEquals(oldValue, 1); + assertEquals(1, oldValue); int value = (int)intHandle_longIndex.get(); - assertEquals(value, 43); + assertEquals(43, value); boolean swapped = (boolean)intHandle_longIndex.compareAndSet(43, 12); assertTrue(swapped); oldValue = (int)intHandle_longIndex.compareAndExchange(12, 42); - assertEquals(oldValue, 12); + assertEquals(12, oldValue); value = (int)intHandle_longIndex.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(); - assertEquals(value, 42); + assertEquals(42, value); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadInsertCoordinatesNegativePos() { - MethodHandles.insertCoordinates(intHandle, -1, 42); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.insertCoordinates(intHandle, -1, 42); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadInsertCoordinatesPosTooBig() { - MethodHandles.insertCoordinates(intHandle, 1, 42); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.insertCoordinates(intHandle, 1, 42); + }); } - @Test(expectedExceptions = ClassCastException.class) + @Test public void testBadInsertCoordinatesWrongCoordinateType() { - MethodHandles.insertCoordinates(intHandleIndexed, 1, "Hello"); + assertThrows(ClassCastException.class, () -> { + MethodHandles.insertCoordinates(intHandleIndexed, 1, "Hello"); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadInsertCoordinatesTooManyValues() { - MethodHandles.insertCoordinates(intHandleIndexed, 1, 0L, 0L); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.insertCoordinates(intHandleIndexed, 1, 0L, 0L); + }); } @Test @@ -301,35 +336,43 @@ public void testPermuteCoordinates() throws Throwable { List.of(long.class, MemorySegment.class), 1, 0); intHandle_swap.set(0L, segment, 1); int oldValue = (int)intHandle_swap.getAndAdd(0L, segment, 42); - assertEquals(oldValue, 1); + assertEquals(1, oldValue); int value = (int)intHandle_swap.get(0L, segment); - assertEquals(value, 43); + assertEquals(43, value); boolean swapped = (boolean)intHandle_swap.compareAndSet(0L, segment, 43, 12); assertTrue(swapped); oldValue = (int)intHandle_swap.compareAndExchange(0L, segment, 12, 42); - assertEquals(oldValue, 12); + assertEquals(12, oldValue); value = (int)intHandle_swap.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(0L, segment); - assertEquals(value, 42); + assertEquals(42, value); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPermuteCoordinatesTooManyCoordinates() { - MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), new int[2]); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), new int[2]); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPermuteCoordinatesTooFewCoordinates() { - MethodHandles.permuteCoordinates(intHandle, List.of()); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.permuteCoordinates(intHandle, List.of()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPermuteCoordinatesIndexTooBig() { - MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), 3); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), 3); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPermuteCoordinatesIndexTooSmall() { - MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), -1); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.permuteCoordinates(intHandle, List.of(int.class, int.class), -1); + }); } @Test @@ -340,41 +383,49 @@ public void testCollectCoordinates() throws Throwable { VarHandle intHandle_sum = MethodHandles.collectCoordinates(intHandleIndexed, 1, SUM_OFFSETS); intHandle_sum.set(segment, -2L, 2L, 1); int oldValue = (int)intHandle_sum.getAndAdd(segment, -2L, 2L, 42); - assertEquals(oldValue, 1); + assertEquals(1, oldValue); int value = (int)intHandle_sum.get(segment, -2L, 2L); - assertEquals(value, 43); + assertEquals(43, value); boolean swapped = (boolean)intHandle_sum.compareAndSet(segment, -2L, 2L, 43, 12); assertTrue(swapped); oldValue = (int)intHandle_sum.compareAndExchange(segment, -2L, 2L, 12, 42); - assertEquals(oldValue, 12); + assertEquals(12, oldValue); value = (int)intHandle_sum.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, -2L, 2L); - assertEquals(value, 42); + assertEquals(42, value); } @Test public void testCollectCoordinatesVoidFilterType() { VarHandle handle = MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER); - assertEquals(handle.coordinateTypes(), List.of(String.class, MemorySegment.class)); + assertEquals(List.of(String.class, MemorySegment.class), handle.coordinateTypes()); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadCollectCoordinatesNegativePos() { - MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadCollectCoordinatesPosTooBig() { - MethodHandles.collectCoordinates(intHandle, 1, SUM_OFFSETS); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.collectCoordinates(intHandle, 1, SUM_OFFSETS); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadCollectCoordinatesWrongFilterType() { - MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadCollectCoordinatesWrongFilterException() { - MethodHandles.collectCoordinates(intHandle, 0, S2L_EX); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.collectCoordinates(intHandle, 0, S2L_EX); + }); } @Test @@ -385,25 +436,29 @@ public void testDropCoordinates() throws Throwable { VarHandle intHandle_dummy = MethodHandles.dropCoordinates(intHandleIndexed, 1, float.class, String.class); intHandle_dummy.set(segment, 1f, "hello", 0L, 1); int oldValue = (int)intHandle_dummy.getAndAdd(segment, 1f, "hello", 0L, 42); - assertEquals(oldValue, 1); + assertEquals(1, oldValue); int value = (int)intHandle_dummy.get(segment, 1f, "hello", 0L); - assertEquals(value, 43); + assertEquals(43, value); boolean swapped = (boolean)intHandle_dummy.compareAndSet(segment, 1f, "hello", 0L, 43, 12); assertTrue(swapped); oldValue = (int)intHandle_dummy.compareAndExchange(segment, 1f, "hello", 0L, 12, 42); - assertEquals(oldValue, 12); + assertEquals(12, oldValue); value = (int)intHandle_dummy.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 1f, "hello", 0L); - assertEquals(value, 42); + assertEquals(42, value); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadDropCoordinatesNegativePos() { - MethodHandles.dropCoordinates(intHandle, -1); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.dropCoordinates(intHandle, -1); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadDropCoordinatesPosTooBig() { - MethodHandles.dropCoordinates(intHandle, 2); + assertThrows(IllegalArgumentException.class, () -> { + MethodHandles.dropCoordinates(intHandle, 2); + }); } //helper methods diff --git a/test/jdk/java/foreign/TestAddressDereference.java b/test/jdk/java/foreign/TestAddressDereference.java index 76ab0086eb93..c617060119e6 100644 --- a/test/jdk/java/foreign/TestAddressDereference.java +++ b/test/jdk/java/foreign/TestAddressDereference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library ../ /test/lib - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestAddressDereference + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestAddressDereference */ import java.lang.foreign.Arena; @@ -41,10 +41,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestAddressDereference extends UpcallTestHelper { static final Linker LINKER = Linker.nativeLinker(); @@ -65,7 +67,8 @@ public class TestAddressDereference extends UpcallTestHelper { } } - @Test(dataProvider = "layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testGetAddress(long alignment, ValueLayout layout) { boolean badAlign = layout.byteAlignment() > alignment; try (Arena arena = Arena.ofConfined()) { @@ -73,14 +76,15 @@ public void testGetAddress(long alignment, ValueLayout layout) { segment.set(ValueLayout.ADDRESS, 0, MemorySegment.ofAddress(alignment)); MemorySegment deref = segment.get(ValueLayout.ADDRESS.withTargetLayout(layout), 0); assertFalse(badAlign); - assertEquals(deref.byteSize(), layout.byteSize()); + assertEquals(layout.byteSize(), deref.byteSize()); } catch (IllegalArgumentException ex) { assertTrue(badAlign); assertTrue(ex.getMessage().contains("alignment constraint for address")); } } - @Test(dataProvider = "layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testGetAddressIndex(long alignment, ValueLayout layout) { boolean badAlign = layout.byteAlignment() > alignment; try (Arena arena = Arena.ofConfined()) { @@ -88,14 +92,15 @@ public void testGetAddressIndex(long alignment, ValueLayout layout) { segment.set(ValueLayout.ADDRESS, 0, MemorySegment.ofAddress(alignment)); MemorySegment deref = segment.getAtIndex(ValueLayout.ADDRESS.withTargetLayout(layout), 0); assertFalse(badAlign); - assertEquals(deref.byteSize(), layout.byteSize()); + assertEquals(layout.byteSize(), deref.byteSize()); } catch (IllegalArgumentException ex) { assertTrue(badAlign); assertTrue(ex.getMessage().contains("alignment constraint for address")); } } - @Test(dataProvider = "layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testNativeReturn(long alignment, ValueLayout layout) throws Throwable { boolean badAlign = layout.byteAlignment() > alignment; try { @@ -103,14 +108,15 @@ public void testNativeReturn(long alignment, ValueLayout layout) throws Throwabl FunctionDescriptor.of(ValueLayout.ADDRESS.withTargetLayout(layout), ValueLayout.ADDRESS)); MemorySegment deref = (MemorySegment)get_addr_handle.invokeExact(MemorySegment.ofAddress(alignment)); assertFalse(badAlign); - assertEquals(deref.byteSize(), layout.byteSize()); + assertEquals(layout.byteSize(), deref.byteSize()); } catch (IllegalArgumentException ex) { assertTrue(badAlign); assertTrue(ex.getMessage().contains("alignment constraint for address")); } } - @Test(dataProvider = "layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testNativeUpcallArgPos(long alignment, ValueLayout layout) throws Throwable { boolean badAlign = layout.byteAlignment() > alignment; if (badAlign) return; // this will crash the JVM (exception occurs when going into the upcall stub) @@ -122,7 +128,8 @@ public void testNativeUpcallArgPos(long alignment, ValueLayout layout) throws Th } } - @Test(dataProvider = "layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testNativeUpcallArgNeg(long alignment, ValueLayout layout) throws Throwable { boolean badAlign = layout.byteAlignment() > alignment; if (!badAlign) return; @@ -154,10 +161,9 @@ static ValueLayout parseLayout(String s) { } static void testArg(MemorySegment deref, long expectedSize) { - assertEquals(deref.byteSize(), expectedSize); + assertEquals(expectedSize, deref.byteSize()); } - @DataProvider(name = "layoutsAndAlignments") static Object[][] layoutsAndAlignments() { List layoutsAndAlignments = new ArrayList<>(); for (LayoutKind lk : LayoutKind.values()) { diff --git a/test/jdk/java/foreign/TestArrayCopy.java b/test/jdk/java/foreign/TestArrayCopy.java index 9a1c48a394e0..b86bfe1266e3 100644 --- a/test/jdk/java/foreign/TestArrayCopy.java +++ b/test/jdk/java/foreign/TestArrayCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestArrayCopy + * @run junit TestArrayCopy */ import java.lang.foreign.MemorySegment; @@ -33,13 +33,15 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * These tests exercise the MemoryCopy copyFromArray(...) and copyToArray(...). @@ -51,6 +53,7 @@ * the copy of the overlapping region is performed as if the data in the overlapping region * were first copied into a temporary segment before being copied to the destination.

*/ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestArrayCopy { private static final ByteOrder NATIVE_ORDER = ByteOrder.nativeOrder(); private static final ByteOrder NON_NATIVE_ORDER = NATIVE_ORDER == ByteOrder.LITTLE_ENDIAN @@ -59,7 +62,8 @@ public class TestArrayCopy { private static final int SEG_LENGTH_BYTES = 32; private static final int SEG_OFFSET_BYTES = 8; - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testSelfCopy(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; @@ -73,7 +77,7 @@ public void testSelfCopy(CopyMode mode, CopyHelper helper, MemorySegment dstSeg = helper.fromArray(srcArr); long dstOffsetBytes = mode.direction ? SEG_OFFSET_BYTES : 0; helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo); - assertEquals(truth.mismatch(dstSeg), -1); + assertEquals(-1, truth.mismatch(dstSeg)); //CopyTo long srcOffsetBytes = mode.direction ? 0 : SEG_OFFSET_BYTES; Object dstArr = helper.toArray(base); @@ -82,10 +86,11 @@ public void testSelfCopy(CopyMode mode, CopyHelper helper, int dstCopyLen = helper.length(dstArr) - indexShifts; helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); MemorySegment result = helper.fromArray(dstArr); - assertEquals(truth.mismatch(result), -1); + assertEquals(-1, truth.mismatch(result)); } - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testUnalignedCopy(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; @@ -107,7 +112,8 @@ public void testUnalignedCopy(CopyMode mode, CopyHelper hel helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); } - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testCopyOobLength(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -131,7 +137,8 @@ public void testCopyOobLength(CopyMode mode, CopyHelper hel } } - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testCopyNegativeIndices(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -155,7 +162,8 @@ public void testCopyNegativeIndices(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -179,7 +187,8 @@ public void testCopyNegativeOffsets(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -203,7 +212,8 @@ public void testCopyOobIndices(CopyMode mode, CopyHelper he } } - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testCopyOobOffsets(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -227,7 +237,8 @@ public void testCopyOobOffsets(CopyMode mode, CopyHelper he } } - @Test(dataProvider = "copyModesAndHelpers") + @ParameterizedTest + @MethodSource("copyModesAndHelpers") public void testCopyReadOnlyDest(CopyMode mode, CopyHelper helper, String helperDebugString) { int bytesPerElement = (int)helper.elementLayout.byteSize(); MemorySegment base = srcSegment(SEG_LENGTH_BYTES); @@ -242,40 +253,52 @@ public void testCopyReadOnlyDest(CopyMode mode, CopyHelper } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNotAnArraySrc() { MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); - MemorySegment.copy(segment, JAVA_BYTE, 0, new String[] { "hello" }, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(segment, JAVA_BYTE, 0, new String[] { "hello" }, 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNotAnArrayDst() { MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); - MemorySegment.copy(new String[] { "hello" }, 0, segment, JAVA_BYTE, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(new String[] { "hello" }, 0, segment, JAVA_BYTE, 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testCarrierMismatchSrc() { MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); - MemorySegment.copy(segment, JAVA_INT, 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(segment, JAVA_INT, 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testCarrierMismatchDst() { MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); - MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testHyperAlignedSrc() { MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); - MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testHyperAlignedDst() { MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); - MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + }); } /***** Utilities *****/ @@ -555,7 +578,6 @@ int length(double[] arr) { }; } - @DataProvider Object[][] copyModesAndHelpers() { CopyHelper[] helpers = { CopyHelper.BYTE, CopyHelper.CHAR, CopyHelper.SHORT, CopyHelper.INT, CopyHelper.FLOAT, CopyHelper.LONG, CopyHelper.DOUBLE }; diff --git a/test/jdk/java/foreign/TestArrays.java b/test/jdk/java/foreign/TestArrays.java index 4406db36750d..2fb86caeba71 100644 --- a/test/jdk/java/foreign/TestArrays.java +++ b/test/jdk/java/foreign/TestArrays.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrays + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestArrays */ import java.lang.foreign.*; @@ -39,7 +39,6 @@ import java.util.function.Consumer; import java.util.function.Function; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_CHAR; @@ -48,8 +47,13 @@ import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_LONG; import static java.lang.foreign.ValueLayout.JAVA_SHORT; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestArrays { static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, @@ -104,7 +108,8 @@ static void checkBytes(MemorySegment base, SequenceLayout layout, Function init, Consumer checker, MemoryLayout layout) { Arena scope = Arena.ofAuto(); MemorySegment segment = scope.allocate(layout); @@ -113,37 +118,42 @@ public void testArrays(Consumer init, Consumer che checker.accept(segment); } - @Test(dataProvider = "elemLayouts", - expectedExceptions = IllegalStateException.class) + @ParameterizedTest + @MethodSource("elemLayouts") public void testTooBigForArray(MemoryLayout layout, Function arrayFactory) { MemoryLayout seq = MemoryLayout.sequenceLayout((Integer.MAX_VALUE * layout.byteSize()) + 1, layout); //do not really allocate here, as it's way too much memory MemorySegment segment = MemorySegment.NULL.reinterpret(seq.byteSize()); - arrayFactory.apply(segment); + assertThrows(IllegalStateException.class, () -> { + arrayFactory.apply(segment); + }); } - @Test(dataProvider = "elemLayouts", - expectedExceptions = IllegalStateException.class) + @ParameterizedTest + @MethodSource("elemLayouts") public void testBadSize(MemoryLayout layout, Function arrayFactory) { - if (layout.byteSize() == 1) throw new IllegalStateException(); //make it fail + if (layout.byteSize() == 1) return; // skip try (Arena arena = Arena.ofConfined()) { long byteSize = layout.byteSize() + 1; long byteAlignment = layout.byteSize(); MemorySegment segment = arena.allocate(byteSize, byteAlignment); - arrayFactory.apply(segment); + assertThrows(IllegalStateException.class, () -> { + arrayFactory.apply(segment); + }); } } - @Test(dataProvider = "elemLayouts", - expectedExceptions = IllegalStateException.class) + @ParameterizedTest + @MethodSource("elemLayouts") public void testArrayFromClosedSegment(MemoryLayout layout, Function arrayFactory) { Arena arena = Arena.ofConfined(); MemorySegment segment = arena.allocate(layout); arena.close(); - arrayFactory.apply(segment); + assertThrows(IllegalStateException.class, () -> { + arrayFactory.apply(segment); + }); } - @DataProvider(name = "arrays") public Object[][] nativeAccessOps() { Consumer byteInitializer = (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, 0L, pos, (byte)(long)pos)); @@ -186,7 +196,6 @@ public Object[][] nativeAccessOps() { }; } - @DataProvider(name = "elemLayouts") public Object[][] elemLayouts() { return new Object[][] { { JAVA_BYTE, (Function)s -> s.toArray(JAVA_BYTE)}, diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index e45bb3fdbf0d..ab65a661ad98 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @modules java.base/sun.nio.ch java.base/jdk.internal.foreign - * @run testng/othervm/timeout=600 --enable-native-access=ALL-UNNAMED TestByteBuffer + * @run junit/othervm/timeout=600 --enable-native-access=ALL-UNNAMED TestByteBuffer */ import java.lang.foreign.*; @@ -67,13 +67,19 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import org.testng.SkipException; -import org.testng.annotations.*; import sun.nio.ch.DirectBuffer; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestByteBuffer { static final Path tempPath; @@ -125,9 +131,9 @@ static void checkTuples(MemorySegment base, ByteBuffer bb, long count) { for (long i = 0; i < count ; i++) { int index; float value; - assertEquals(index = bb.getInt(), (int)indexHandle.get(base, 0L, i)); - assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, 0L, i)); - assertEquals(value, index / 500f); + assertEquals((int)indexHandle.get(base, 0L, i), index = bb.getInt()); + assertEquals((float)valueHandle.get(base, 0L, i), value = bb.getFloat()); + assertEquals(index / 500f, value); } } @@ -154,13 +160,13 @@ static void checkBytes(MemorySegment base, SequenceLayout lay Object bufferValue = bufferExtractor.apply(z); Object handleViewValue = handleExtractor.apply(segmentBufferView, j - i); if (handleValue instanceof Number) { - assertEquals(((Number)handleValue).longValue(), j); - assertEquals(((Number)bufferValue).longValue(), j); - assertEquals(((Number)handleViewValue).longValue(), j); + assertEquals(j, ((Number)handleValue).longValue()); + assertEquals(j, ((Number)bufferValue).longValue()); + assertEquals(j, ((Number)handleViewValue).longValue()); } else { - assertEquals((long)(char)handleValue, j); - assertEquals((long)(char)bufferValue, j); - assertEquals((long)(char)handleViewValue, j); + assertEquals(j, (long)(char)handleValue); + assertEquals(j, (long)(char)bufferValue); + assertEquals(j, (long)(char)handleViewValue); } } } @@ -248,19 +254,21 @@ public void testMappedSegment() throws Throwable { } } - @Test(dataProvider = "mappedOps", expectedExceptions = IllegalStateException.class) + @ParameterizedTest + @MethodSource("mappedOps") public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable { File f = new File("test3.out"); f.createNewFile(); f.deleteOnExit(); - Arena arena = Arena.ofConfined(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena); assertTrue(segment.isMapped()); assertTrue(segment.toString().contains("mapped")); arena.close(); - mappedBufferOp.apply(segment); + assertThrows(IllegalStateException.class, () -> { + mappedBufferOp.apply(segment); + }); } } @@ -294,7 +302,8 @@ public void testMappedSegmentOffset() throws Throwable { } } - @Test(dataProvider = "fromArrays") + @ParameterizedTest + @MethodSource("fromArrays") public void testAsByteBufferFromNonByteArray(MemorySegment segment) { if (!segment.heapBase().map(a -> a instanceof byte[]).get()) { // This should not work as the segment is not backed by a byte array @@ -318,12 +327,12 @@ public void testMappedSegmentAsByteBuffer() throws Throwable { segment.isLoaded(); segment.unload(); ByteBuffer byteBuffer = segment.asByteBuffer(); - assertEquals(byteBuffer.capacity(), segment.byteSize()); - assertEquals(byteBuffer.isReadOnly(), segment.isReadOnly()); + assertEquals(segment.byteSize(), byteBuffer.capacity()); + assertEquals(segment.isReadOnly(), byteBuffer.isReadOnly()); assertTrue(byteBuffer.isDirect()); } catch (IOException e) { - if (e.getMessage().equals("Function not implemented")) - throw new SkipException(e.getMessage(), e); + assumeFalse(e.getMessage().equals("Function not implemented"), + e.getMessage()); } finally { if (arena.scope() != Arena.global().scope()) { arena.close(); @@ -337,9 +346,7 @@ public void testMappedSegmentAsByteBuffer() throws Throwable { @Test public void testLargeMappedSegment() throws Throwable { - if (System.getProperty("sun.arch.data.model").equals("32")) { - throw new SkipException("large mapped files not supported on 32-bit systems"); - } + assumeFalse(System.getProperty("sun.arch.data.model").equals("32"), "large mapped files not supported on 32-bit systems"); File f = new File("testLargeMappedSegment.out"); f.createNewFile(); @@ -356,8 +363,8 @@ public void testLargeMappedSegment() throws Throwable { segment.unload(); segment.isLoaded(); } catch(IOException e) { - if (e.getMessage().equals("Function not implemented")) - throw new SkipException(e.getMessage(), e); + assumeFalse(e.getMessage().equals("Function not implemented"), + e.getMessage()); } } @@ -374,14 +381,13 @@ static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long } static void checkByteArrayAlignment(MemoryLayout layout) { - if (layout.byteSize() > 4 - && System.getProperty("sun.arch.data.model").equals("32")) { - throw new SkipException("avoid unaligned access on 32-bit system"); - } + assumeFalse(layout.byteSize() > 4 + && System.getProperty("sun.arch.data.model").equals("32"), "avoid unaligned access on 32-bit system"); } - @Test(dataProvider = "bufferOps") - public void testScopedBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { + @ParameterizedTest + @MethodSource("bufferOps") + public void testScopedBuffer(Function bufferFactory, Method method, Object[] args) { Buffer bb; try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(bytes); @@ -406,7 +412,8 @@ public void testScopedBuffer(Function bufferFactory, @NoInje } } - @Test(dataProvider = "bufferHandleOps") + @ParameterizedTest + @MethodSource("bufferHandleOps") public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { ByteBuffer bb; try (Arena arena = Arena.ofConfined()) { @@ -441,20 +448,22 @@ public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { } } - @Test(dataProvider = "bufferOps") - public void testDirectBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { + @ParameterizedTest + @MethodSource("bufferOps") + public void testDirectBuffer(Function bufferFactory, Method method, Object[] args) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(bytes); Buffer bb = bufferFactory.apply(segment.asByteBuffer()); assertTrue(bb.isDirect()); DirectBuffer directBuffer = ((DirectBuffer)bb); - assertEquals(directBuffer.address(), segment.address()); + assertEquals(segment.address(), directBuffer.address()); assertTrue((directBuffer.attachment() == null) == (bb instanceof ByteBuffer)); assertTrue(directBuffer.cleaner() == null); } } - @Test(dataProvider="resizeOps") + @ParameterizedTest + @MethodSource("resizeOps") public void testResizeOffheap(Consumer checker, Consumer initializer, SequenceLayout seq) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(seq); @@ -463,7 +472,8 @@ public void testResizeOffheap(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int capacity = (int)seq.byteSize(); @@ -472,7 +482,8 @@ public void testResizeHeap(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int capacity = (int)seq.byteSize(); @@ -481,7 +492,8 @@ public void testResizeBuffer(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int capacity = (int)seq.byteSize(); @@ -492,7 +504,8 @@ public void testResizeRoundtripHeap(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(seq); @@ -502,39 +515,47 @@ public void testResizeRoundtripNative(Consumer checker, Consumer< } } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testBufferOnClosedSession() { MemorySegment leaked; try (Arena arena = Arena.ofConfined()) { leaked = arena.allocate(bytes); } ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok - byteBuffer.get(); // should throw + assertThrows(IllegalStateException.class, () -> { + byteBuffer.get(); + }); } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testTooBigForByteBuffer() { MemorySegment segment = MemorySegment.NULL.reinterpret(Integer.MAX_VALUE + 10L); - segment.asByteBuffer(); + assertThrows(IllegalStateException.class, () -> { + segment.asByteBuffer(); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadMapNegativeSize() throws IOException { File f = new File("testNeg1.out"); f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, Arena.ofAuto()); + assertThrows(IllegalArgumentException.class, () -> { + fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, Arena.ofAuto()); + }); } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadMapNegativeOffset() throws IOException { File f = new File("testNeg2.out"); f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, Arena.ofAuto()); + assertThrows(IllegalArgumentException.class, () -> { + fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, Arena.ofAuto()); + }); } } @@ -559,7 +580,7 @@ public void testMapOffset() throws IOException { try (Arena arena = Arena.ofConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, arena); - assertEquals(segment.get(JAVA_BYTE, 0), offset); + assertEquals(offset, segment.get(JAVA_BYTE, 0)); } } } @@ -573,30 +594,30 @@ public void testMapZeroSize() throws IOException { try (Arena arena = Arena.ofConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, arena); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.isMapped(), true); + assertEquals(0, segment.byteSize()); + assertEquals(true, segment.isMapped()); assertFalse(segment.isReadOnly()); segment.force(); segment.load(); segment.isLoaded(); segment.unload(); ByteBuffer byteBuffer = segment.asByteBuffer(); - assertEquals(byteBuffer.capacity(), 0); + assertEquals(0, byteBuffer.capacity()); assertFalse(byteBuffer.isReadOnly()); } //RO try (Arena arena = Arena.ofConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, arena); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.isMapped(), true); + assertEquals(0, segment.byteSize()); + assertEquals(true, segment.isMapped()); assertTrue(segment.isReadOnly()); segment.force(); segment.load(); segment.isLoaded(); segment.unload(); ByteBuffer byteBuffer = segment.asByteBuffer(); - assertEquals(byteBuffer.capacity(), 0); + assertEquals(0, byteBuffer.capacity()); assertTrue(byteBuffer.isReadOnly()); } } @@ -622,7 +643,8 @@ public void testMapCustomPath() throws IOException { } } - @Test(dataProvider="resizeOps") + @ParameterizedTest + @MethodSource("resizeOps") public void testCopyHeapToNative(Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); @@ -635,7 +657,8 @@ public void testCopyHeapToNative(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); @@ -685,28 +708,30 @@ public void testOfBufferScopeReachable() throws InterruptedException { } } - @Test(dataProvider="bufferSources") + @ParameterizedTest + @MethodSource("bufferSources") public void testBufferToSegment(ByteBuffer bb, Predicate segmentChecker) { MemorySegment segment = MemorySegment.ofBuffer(bb); - assertEquals(segment.isReadOnly(), bb.isReadOnly()); + assertEquals(bb.isReadOnly(), segment.isReadOnly()); assertTrue(segmentChecker.test(segment)); assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize()))); - assertEquals(bb.capacity(), segment.byteSize()); + assertEquals(segment.byteSize(), bb.capacity()); //another round trip segment = MemorySegment.ofBuffer(segment.asByteBuffer()); - assertEquals(segment.isReadOnly(), bb.isReadOnly()); + assertEquals(bb.isReadOnly(), segment.isReadOnly()); assertTrue(segmentChecker.test(segment)); assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize()))); - assertEquals(bb.capacity(), segment.byteSize()); + assertEquals(segment.byteSize(), bb.capacity()); } - @Test(dataProvider="bufferSources") + @ParameterizedTest + @MethodSource("bufferSources") public void bufferProperties(ByteBuffer bb, Predicate _unused) { MemorySegment segment = MemorySegment.ofBuffer(bb); ByteBuffer buffer = segment.asByteBuffer(); - assertEquals(buffer.position(), 0); - assertEquals(buffer.capacity(), segment.byteSize()); - assertEquals(buffer.limit(), segment.byteSize()); + assertEquals(0, buffer.position()); + assertEquals(segment.byteSize(), buffer.capacity()); + assertEquals(segment.byteSize(), buffer.limit()); } @Test @@ -715,27 +740,28 @@ public void testRoundTripAccess() { MemorySegment ms = arena.allocate(4, 1); MemorySegment msNoAccess = ms.asReadOnly(); MemorySegment msRoundTrip = MemorySegment.ofBuffer(msNoAccess.asByteBuffer()); - assertEquals(msRoundTrip.scope(), ms.scope()); - assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly()); + assertEquals(ms.scope(), msRoundTrip.scope()); + assertEquals(msRoundTrip.isReadOnly(), msNoAccess.isReadOnly()); } } - @Test(dataProvider = "bufferFactories") + @ParameterizedTest + @MethodSource("bufferFactories") public void testDerivedBufferScopes(Supplier bufferFactory) { MemorySegment segment = MemorySegment.ofBuffer(bufferFactory.get()); assertEquals(segment.scope(), segment.scope()); // one level - assertEquals(segment.asSlice(0).scope(), segment.scope()); - assertEquals(segment.asReadOnly().scope(), segment.scope()); + assertEquals(segment.scope(), segment.asSlice(0).scope()); + assertEquals(segment.scope(), segment.asReadOnly().scope()); // two levels - assertEquals(segment.asSlice(0).asReadOnly().scope(), segment.scope()); - assertEquals(segment.asReadOnly().asSlice(0).scope(), segment.scope()); + assertEquals(segment.scope(), segment.asSlice(0).asReadOnly().scope()); + assertEquals(segment.scope(), segment.asReadOnly().asSlice(0).scope()); // check fresh every time MemorySegment another = MemorySegment.ofBuffer(bufferFactory.get()); - assertNotEquals(segment.scope(), another.scope()); + assertNotEquals(another.scope(), segment.scope()); } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testDeadAccessOnClosedBufferSegment() { Arena arena = Arena.ofConfined(); MemorySegment s1 = arena.allocate(JAVA_INT); @@ -743,11 +769,13 @@ public void testDeadAccessOnClosedBufferSegment() { // memory freed arena.close(); - - s2.set(JAVA_INT, 0, 10); // Dead access! + assertThrows(IllegalStateException.class, () -> { + s2.set(JAVA_INT, 0, 10); // Dead access! + }); } - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void closeableArenas(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); @@ -758,17 +786,18 @@ public void closeableArenas(Supplier arenaSupplier) throws IOException { segment.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb = segment.asByteBuffer(); - assertEquals(channel.write(bb), 10); + assertEquals(10, channel.write(bb)); segment.fill((byte)0x00); - assertEquals(bb.clear(), ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); - assertEquals(channel.position(0).read(bb.clear()), 10); - assertEquals(bb.flip(), ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + assertEquals(ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), bb.clear()); + assertEquals(10, channel.position(0).read(bb.clear())); + assertEquals(ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), bb.flip()); } } static final Class ISE = IllegalStateException.class; - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testIOOnClosedSegmentBuffer(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); @@ -797,13 +826,13 @@ public void buffersAndArraysFromSlices() { var slice = segment.asSlice(4, newSize); var bytes = slice.toArray(JAVA_BYTE); - assertEquals(newSize, bytes.length); + assertEquals(bytes.length, newSize); var buffer = slice.asByteBuffer(); // Fails for heap segments, but passes for native segments: assertEquals(0, buffer.position()); - assertEquals(newSize, buffer.limit()); - assertEquals(newSize, buffer.capacity()); + assertEquals(buffer.limit(), newSize); + assertEquals(buffer.capacity(), newSize); } } @@ -817,7 +846,6 @@ public void viewsFromSharedSegment() { } } - @DataProvider(name = "segments") public static Object[][] segments() throws Throwable { return new Object[][] { { (Supplier) () -> Arena.ofAuto().allocate(16, 1)}, @@ -826,7 +854,6 @@ public static Object[][] segments() throws Throwable { }; } - @DataProvider(name = "closeableArenas") public static Object[][] closeableArenas() { return new Object[][] { { (Supplier) Arena::ofConfined}, @@ -834,7 +861,6 @@ public static Object[][] closeableArenas() { }; } - @DataProvider(name = "bufferOps") public static Object[][] bufferOps() throws Throwable { List args = new ArrayList<>(); bufferOpsArgs(args, bb -> bb, ByteBuffer.class); @@ -861,7 +887,6 @@ static void bufferOpsArgs(List argsList, Function } } - @DataProvider(name = "bufferHandleOps") public static Object[][] bufferHandleOps() throws Throwable { return new Object[][]{ { MethodHandles.byteBufferViewVarHandle(char[].class, ByteOrder.nativeOrder()) }, @@ -889,7 +914,6 @@ static Map varHandleMembers(ByteBuffer bb, VarHandle han return members; } - @DataProvider(name = "resizeOps") public Object[][] resizeOps() { Consumer byteInitializer = (base) -> initBytes(base, bytes, (addr, pos) -> addr.set(JAVA_BYTE, pos, (byte)(long)pos)); @@ -994,7 +1018,6 @@ static Object defaultValue(Class c) { } } - @DataProvider(name = "bufferSources") public static Object[][] bufferSources() { Predicate heapTest = segment -> !segment.isNative() && !segment.isMapped(); Predicate nativeTest = segment -> segment.isNative() && !segment.isMapped(); @@ -1038,14 +1061,12 @@ void apply(MemorySegment segment) { } } - @DataProvider(name = "mappedOps") public static Object[][] mappedOps() { return Stream.of(MappedSegmentOp.values()) .map(op -> new Object[] { op }) .toArray(Object[][]::new); } - @DataProvider(name = "bufferFactories") public static Object[][] bufferFactories() { List> l = List.of( () -> ByteBuffer.allocate(10), @@ -1066,7 +1087,6 @@ public static Object[][] bufferFactories() { return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } - @DataProvider(name = "fromArrays") public static Object[][] fromArrays() { int len = 16; return Stream.of( diff --git a/test/jdk/java/foreign/TestClassLoaderFindNative.java b/test/jdk/java/foreign/TestClassLoaderFindNative.java index 9d04a7f83af1..a11b8ef2a670 100644 --- a/test/jdk/java/foreign/TestClassLoaderFindNative.java +++ b/test/jdk/java/foreign/TestClassLoaderFindNative.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * 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,17 +23,18 @@ /* * @test - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestClassLoaderFindNative + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestClassLoaderFindNative */ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.foreign.SymbolLookup; import java.nio.ByteOrder; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; // FYI this test is run on 64-bit platforms only for now, // since the windows 32-bit linker fails and there @@ -58,7 +59,7 @@ public void testInvalidSymbolLookup() { @Test public void testVariableSymbolLookup() { MemorySegment segment = SymbolLookup.loaderLookup().find("c").get().reinterpret(4); - assertEquals(segment.get(JAVA_INT, 0), 42); + assertEquals(42, segment.get(JAVA_INT, 0)); } @Test diff --git a/test/jdk/java/foreign/TestConcurrentClose.java b/test/jdk/java/foreign/TestConcurrentClose.java index 74f0ca2a8774..1d2b02ed8e04 100644 --- a/test/jdk/java/foreign/TestConcurrentClose.java +++ b/test/jdk/java/foreign/TestConcurrentClose.java @@ -31,7 +31,7 @@ * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * - * @run testng/othervm/timeout=480 + * @run junit/othervm/timeout=480 * -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI @@ -41,7 +41,6 @@ */ import jdk.test.whitebox.WhiteBox; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -53,7 +52,9 @@ import java.util.concurrent.atomic.AtomicLong; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.assertFalse; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import org.junit.jupiter.api.Test; public class TestConcurrentClose { static final WhiteBox WB = WhiteBox.getWhiteBox(); diff --git a/test/jdk/java/foreign/TestDereferencePath.java b/test/jdk/java/foreign/TestDereferencePath.java index e2281cde235e..c3706f0e79de 100644 --- a/test/jdk/java/foreign/TestDereferencePath.java +++ b/test/jdk/java/foreign/TestDereferencePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test - * @run testng TestDereferencePath + * @run junit TestDereferencePath */ import java.lang.foreign.Arena; @@ -34,10 +34,11 @@ import java.lang.foreign.ValueLayout; -import org.testng.annotations.*; import java.lang.invoke.VarHandle; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestDereferencePath { @@ -73,7 +74,7 @@ public void testSingle() { c.set(ValueLayout.JAVA_INT, 0, 42); // dereference int val = (int) abcx.get(a, 0L); - assertEquals(val, 42); + assertEquals(42, val); } } @@ -109,13 +110,13 @@ public void testMulti() { c.setAtIndex(ValueLayout.JAVA_INT, 3, 4); // dereference int val00 = (int) abcx_multi.get(a, 0L, 0, 0); // a->b[0]->c[0] = 1 - assertEquals(val00, 1); + assertEquals(1, val00); int val10 = (int) abcx_multi.get(a, 0L, 1, 0); // a->b[1]->c[0] = 3 - assertEquals(val10, 3); + assertEquals(3, val10); int val01 = (int) abcx_multi.get(a, 0L, 0, 1); // a->b[0]->c[1] = 2 - assertEquals(val01, 2); + assertEquals(2, val01); int val11 = (int) abcx_multi.get(a, 0L, 1, 1); // a->b[1]->c[1] = 4 - assertEquals(val11, 4); + assertEquals(4, val11); } } @@ -138,44 +139,53 @@ public void testDerefValue() { b.set(ValueLayout.JAVA_INT, 0, 42); // dereference int val = (int) a_value.get(a, 0L); - assertEquals(val, 42); + assertEquals(42, val); } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testBadDerefInSelect() { - A.select(PathElement.groupElement("b"), PathElement.dereferenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + A.select(PathElement.groupElement("b"), PathElement.dereferenceElement()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testBadDerefInOffset() { - A.byteOffset(PathElement.groupElement("b"), PathElement.dereferenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + A.byteOffset(PathElement.groupElement("b"), PathElement.dereferenceElement()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void testBadDerefInSlice() { - A.sliceHandle(PathElement.groupElement("b"), PathElement.dereferenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + A.sliceHandle(PathElement.groupElement("b"), PathElement.dereferenceElement()); + }); } static final MemoryLayout A_MULTI_NO_TARGET = MemoryLayout.structLayout( ValueLayout.ADDRESS.withName("bs") ); - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void badDerefAddressNoTarget() { - A_MULTI_NO_TARGET.varHandle(PathElement.groupElement("bs"), PathElement.dereferenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + A_MULTI_NO_TARGET.varHandle(PathElement.groupElement("bs"), PathElement.dereferenceElement()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test void badDerefMisAligned() { MemoryLayout struct = MemoryLayout.structLayout( - ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_INT).withName("x")); - + ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_INT).withName("x")); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(struct.byteSize() + 1, struct.byteAlignment()).asSlice(1); VarHandle vhX = struct.varHandle(PathElement.groupElement("x"), PathElement.dereferenceElement()); - vhX.set(segment, 0L, 42); // should throw + assertThrows(IllegalArgumentException.class, () -> { + vhX.set(segment, 0L, 42); + }); } } } diff --git a/test/jdk/java/foreign/TestDowncallBase.java b/test/jdk/java/foreign/TestDowncallBase.java index ace8867000f0..66a4bb902e86 100644 --- a/test/jdk/java/foreign/TestDowncallBase.java +++ b/test/jdk/java/foreign/TestDowncallBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,9 @@ import java.util.function.Consumer; import java.util.stream.Stream; +import org.junit.jupiter.api.TestInstance; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestDowncallBase extends CallGeneratorHelper { Object doCall(MemorySegment symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { diff --git a/test/jdk/java/foreign/TestDowncallScope.java b/test/jdk/java/foreign/TestDowncallScope.java index 860fa74b533e..8b2bd75a89c1 100644 --- a/test/jdk/java/foreign/TestDowncallScope.java +++ b/test/jdk/java/foreign/TestDowncallScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,31 +26,35 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 * TestDowncallScope * - * @run testng/othervm/native -Xint -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native -Xint -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=100000 * TestDowncallScope */ -import org.testng.annotations.Test; import java.lang.foreign.*; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestDowncallScope extends TestDowncallBase { static { System.loadLibrary("TestDowncall"); } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testDowncall(int count, String fName, CallGeneratorHelper.Ret ret, List paramTypes, List fields) throws Throwable { @@ -68,7 +72,7 @@ public void testDowncall(int count, String fName, CallGeneratorHelper.Ret ret, checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).scope(), arena.scope()); + assertEquals(arena.scope(), ((MemorySegment)res).scope()); } } } diff --git a/test/jdk/java/foreign/TestDowncallStack.java b/test/jdk/java/foreign/TestDowncallStack.java index 516a8a7e958c..193548405c72 100644 --- a/test/jdk/java/foreign/TestDowncallStack.java +++ b/test/jdk/java/foreign/TestDowncallStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,27 +26,31 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 * TestDowncallStack */ -import org.testng.annotations.Test; import java.lang.foreign.*; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestDowncallStack extends TestDowncallBase { static { System.loadLibrary("TestDowncallStack"); } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testDowncallStack(int count, String fName, CallGeneratorHelper.Ret ret, List paramTypes, List fields) throws Throwable { @@ -64,7 +68,7 @@ public void testDowncallStack(int count, String fName, CallGeneratorHelper.Ret r checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).scope(), arena.scope()); + assertEquals(arena.scope(), ((MemorySegment)res).scope()); } } } diff --git a/test/jdk/java/foreign/TestFallbackLookup.java b/test/jdk/java/foreign/TestFallbackLookup.java index 5cc78bf747ca..939f72bf8a5d 100644 --- a/test/jdk/java/foreign/TestFallbackLookup.java +++ b/test/jdk/java/foreign/TestFallbackLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * 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,14 +23,15 @@ /* * @test - * @run testng/othervm -Dos.name=Windows --enable-native-access=ALL-UNNAMED TestFallbackLookup + * @run junit/othervm -Dos.name=Windows --enable-native-access=ALL-UNNAMED TestFallbackLookup */ -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import java.lang.foreign.Linker; +import org.junit.jupiter.api.Test; + public class TestFallbackLookup { @Test void testBadSystemLookupRequest() { diff --git a/test/jdk/java/foreign/TestFree.java b/test/jdk/java/foreign/TestFree.java index 31e9d9906e16..968eb6943d11 100644 --- a/test/jdk/java/foreign/TestFree.java +++ b/test/jdk/java/foreign/TestFree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,12 @@ * @test * @bug 8248421 * @summary SystemCLinker should have a way to free memory allocated outside Java - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFree + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestFree */ import java.lang.foreign.MemorySegment; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class TestFree extends NativeTestHelper { public void test() throws Throwable { @@ -38,7 +38,7 @@ public void test() throws Throwable { MemorySegment addr = allocateMemory(str.length() + 1); addr.copyFrom(MemorySegment.ofArray(str.getBytes())); addr.set(C_CHAR, str.length(), (byte)0); - assertEquals(str, addr.getString(0)); + assertEquals(addr.getString(0), str); freeMemory(addr); } } diff --git a/test/jdk/java/foreign/TestFunctionDescriptor.java b/test/jdk/java/foreign/TestFunctionDescriptor.java index ef06f1048b20..858bc0f022c7 100644 --- a/test/jdk/java/foreign/TestFunctionDescriptor.java +++ b/test/jdk/java/foreign/TestFunctionDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFunctionDescriptor + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestFunctionDescriptor */ import java.lang.foreign.FunctionDescriptor; @@ -32,9 +32,9 @@ import java.lang.invoke.MethodType; import java.util.List; import java.util.Optional; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestFunctionDescriptor extends NativeTestHelper { @@ -44,17 +44,17 @@ public class TestFunctionDescriptor extends NativeTestHelper { public void testOf() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); + assertEquals(List.of(C_DOUBLE, C_LONG_LONG), fd.argumentLayouts()); Optional returnLayoutOp = fd.returnLayout(); assertTrue(returnLayoutOp.isPresent()); - assertEquals(returnLayoutOp.get(), C_INT); + assertEquals(C_INT, returnLayoutOp.get()); } @Test public void testOfVoid() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_LONG_LONG); - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); + assertEquals(List.of(C_DOUBLE, C_LONG_LONG), fd.argumentLayouts()); Optional returnLayoutOp = fd.returnLayout(); assertFalse(returnLayoutOp.isPresent()); } @@ -64,10 +64,10 @@ public void testAppendArgumentLayouts() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); fd = fd.appendArgumentLayouts(C_POINTER); - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG, C_POINTER)); + assertEquals(List.of(C_DOUBLE, C_LONG_LONG, C_POINTER), fd.argumentLayouts()); Optional returnLayoutOp = fd.returnLayout(); assertTrue(returnLayoutOp.isPresent()); - assertEquals(returnLayoutOp.get(), C_INT); + assertEquals(C_INT, returnLayoutOp.get()); } @Test @@ -75,10 +75,10 @@ public void testChangeReturnLayout() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); fd = fd.changeReturnLayout(C_INT); - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); + assertEquals(List.of(C_DOUBLE, C_LONG_LONG), fd.argumentLayouts()); Optional returnLayoutOp = fd.returnLayout(); assertTrue(returnLayoutOp.isPresent()); - assertEquals(returnLayoutOp.get(), C_INT); + assertEquals(C_INT, returnLayoutOp.get()); } @Test @@ -86,7 +86,7 @@ public void testDropReturnLayout() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); fd = fd.dropReturnLayout(); - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); + assertEquals(List.of(C_DOUBLE, C_LONG_LONG), fd.argumentLayouts()); Optional returnLayoutOp = fd.returnLayout(); assertFalse(returnLayoutOp.isPresent()); } @@ -110,44 +110,58 @@ public void testCarrierMethodType() { MemoryLayout.structLayout(C_INT, C_INT), MemoryLayout.sequenceLayout(3, C_INT)); MethodType cmt = fd.toMethodType(); - assertEquals(cmt, MethodType.methodType(int.class, int.class, MemorySegment.class, MemorySegment.class)); + assertEquals(MethodType.methodType(int.class, int.class, MemorySegment.class, MemorySegment.class), cmt); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testIllegalInsertArgNegIndex() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT); - fd.insertArgumentLayouts(-1, C_INT); + assertThrows(IllegalArgumentException.class, () -> { + fd.insertArgumentLayouts(-1, C_INT); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testIllegalInsertArgOutOfBounds() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT); - fd.insertArgumentLayouts(2, C_INT); + assertThrows(IllegalArgumentException.class, () -> { + fd.insertArgumentLayouts(2, C_INT); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPaddingInVoidFunction() { - FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(1)); + assertThrows(IllegalArgumentException.class, () -> { + FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPaddingInNonVoidFunction() { - FunctionDescriptor.of(MemoryLayout.paddingLayout(1)); + assertThrows(IllegalArgumentException.class, () -> { + FunctionDescriptor.of(MemoryLayout.paddingLayout(1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPaddingInAppendArgLayouts() { - FunctionDescriptor.ofVoid().appendArgumentLayouts(MemoryLayout.paddingLayout(1)); + assertThrows(IllegalArgumentException.class, () -> { + FunctionDescriptor.ofVoid().appendArgumentLayouts(MemoryLayout.paddingLayout(1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPaddingInInsertArgLayouts() { - FunctionDescriptor.ofVoid().insertArgumentLayouts(0, MemoryLayout.paddingLayout(1)); + assertThrows(IllegalArgumentException.class, () -> { + FunctionDescriptor.ofVoid().insertArgumentLayouts(0, MemoryLayout.paddingLayout(1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadPaddingInChangeRetLayout() { - FunctionDescriptor.ofVoid().changeReturnLayout(MemoryLayout.paddingLayout(1)); + assertThrows(IllegalArgumentException.class, () -> { + FunctionDescriptor.ofVoid().changeReturnLayout(MemoryLayout.paddingLayout(1)); + }); } } diff --git a/test/jdk/java/foreign/TestHFA.java b/test/jdk/java/foreign/TestHFA.java index 40f2bf2f305c..927a2114c24a 100644 --- a/test/jdk/java/foreign/TestHFA.java +++ b/test/jdk/java/foreign/TestHFA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,17 +26,18 @@ * @test * @summary Test passing of Homogeneous Float Aggregates. * - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestHFA + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestHFA */ import java.lang.foreign.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.*; +import org.junit.jupiter.api.Test; + public class TestHFA { static { @@ -108,7 +109,7 @@ public class TestHFA { fdpass_large_struct_after_structs); @Test - public static void testAddFloatStructs() { + public void testAddFloatStructs() { float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFFFFFFLayout); @@ -136,7 +137,7 @@ public static void testAddFloatStructs() { } @Test - public static void testAddFloatToStructAfterFloats() { + public void testAddFloatToStructAfterFloats() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -156,7 +157,7 @@ public static void testAddFloatToStructAfterFloats() { } @Test - public static void testAddFloatToStructAfterStructs() { + public void testAddFloatToStructAfterStructs() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -175,7 +176,7 @@ public static void testAddFloatToStructAfterStructs() { } @Test - public static void testAddDoubleToStructAfterStructs() { + public void testAddDoubleToStructAfterStructs() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -194,7 +195,7 @@ public static void testAddDoubleToStructAfterStructs() { } @Test - public static void testAddFloatToLargeStructAfterStructs() { + public void testAddFloatToLargeStructAfterStructs() { float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFFFFFFLayout); @@ -270,7 +271,7 @@ public static MemorySegment addDoubleToStructAfterStructs( } @Test - public static void testAddFloatStructsUpcall() { + public void testAddFloatStructsUpcall() { float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFFFFFFLayout); @@ -302,7 +303,7 @@ public static void testAddFloatStructsUpcall() { } @Test - public static void testAddFloatToStructAfterFloatsUpcall() { + public void testAddFloatToStructAfterFloatsUpcall() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -326,7 +327,7 @@ public static void testAddFloatToStructAfterFloatsUpcall() { } @Test - public static void testAddFloatToStructAfterStructsUpcall() { + public void testAddFloatToStructAfterStructsUpcall() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -349,7 +350,7 @@ public static void testAddFloatToStructAfterStructsUpcall() { } @Test - public static void testAddDoubleToStructAfterStructsUpcall() { + public void testAddDoubleToStructAfterStructsUpcall() { float p0 = 0.0f, p1 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFLayout); @@ -372,7 +373,7 @@ public static void testAddDoubleToStructAfterStructsUpcall() { } @Test - public static void testAddFloatToLargeStructAfterStructsUpcall() { + public void testAddFloatToLargeStructAfterStructsUpcall() { float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(S_FFFFFFFLayout); diff --git a/test/jdk/java/foreign/TestHandshake.java b/test/jdk/java/foreign/TestHandshake.java index 86200b0e7d69..c2bbadc77efa 100644 --- a/test/jdk/java/foreign/TestHandshake.java +++ b/test/jdk/java/foreign/TestHandshake.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,10 @@ * @requires vm.flavor != "zero" * @modules java.base/jdk.internal.vm.annotation java.base/jdk.internal.misc * @key randomness - * @run testng/othervm TestHandshake - * @run testng/othervm -Xint TestHandshake - * @run testng/othervm -XX:TieredStopAtLevel=1 TestHandshake - * @run testng/othervm -XX:-TieredCompilation TestHandshake + * @run junit/othervm TestHandshake + * @run junit/othervm -Xint TestHandshake + * @run junit/othervm -XX:TieredStopAtLevel=1 TestHandshake + * @run junit/othervm -XX:-TieredCompilation TestHandshake */ import java.lang.foreign.Arena; @@ -46,13 +46,16 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestHandshake { static final int ITERATIONS = 5; @@ -66,7 +69,8 @@ public class TestHandshake { static final AtomicLong start = new AtomicLong(); static final AtomicBoolean started = new AtomicBoolean(); - @Test(dataProvider = "accessors") + @ParameterizedTest + @MethodSource("accessors") public void testHandshake(String testName, AccessorFactory accessorFactory) throws InterruptedException { for (int it = 0 ; it < ITERATIONS ; it++) { Arena arena = Arena.ofShared(); @@ -286,7 +290,6 @@ interface AccessorFactory { AbstractSegmentAccessor make(int id, MemorySegment segment, Arena arena); } - @DataProvider static Object[][] accessors() { return new Object[][] { { "SegmentAccessor", (AccessorFactory)SegmentAccessor::new }, diff --git a/test/jdk/java/foreign/TestHeapAlignment.java b/test/jdk/java/foreign/TestHeapAlignment.java index cc8a95465108..328c0da6833f 100644 --- a/test/jdk/java/foreign/TestHeapAlignment.java +++ b/test/jdk/java/foreign/TestHeapAlignment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment */ import java.lang.foreign.AddressLayout; @@ -34,14 +34,17 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Function; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestHeapAlignment { - @Test(dataProvider = "layouts") + @ParameterizedTest + @MethodSource("layouts") public void testHeapAlignment(MemorySegment segment, int align, Object val, Object arr, ValueLayout layout, Function segmentFactory) { assertAligned(align, layout, () -> layout.varHandle().get(segment, 0L)); assertAligned(align, layout, () -> layout.varHandle().set(segment, 0L, val)); @@ -101,7 +104,6 @@ enum SegmentAndAlignment { } } - @DataProvider public static Object[][] layouts() { List layouts = new ArrayList<>(); for (SegmentAndAlignment testCase : SegmentAndAlignment.values()) { diff --git a/test/jdk/java/foreign/TestIllegalLink.java b/test/jdk/java/foreign/TestIllegalLink.java index 45239e3cb458..995efd199d63 100644 --- a/test/jdk/java/foreign/TestIllegalLink.java +++ b/test/jdk/java/foreign/TestIllegalLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @modules java.base/jdk.internal.foreign - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink */ import java.lang.foreign.Arena; @@ -42,14 +42,18 @@ import java.util.List; import jdk.internal.foreign.CABI; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestIllegalLink extends NativeTestHelper { private static final boolean IS_SYSV = CABI.current() == CABI.SYS_V; @@ -59,7 +63,8 @@ public class TestIllegalLink extends NativeTestHelper { private static final MethodHandle DUMMY_TARGET_MH = MethodHandles.empty(MethodType.methodType(void.class)); private static final Linker ABI = Linker.nativeLinker(); - @Test(dataProvider = "types") + @ParameterizedTest + @MethodSource("types") public void testIllegalLayouts(FunctionDescriptor desc, Linker.Option[] options, String expectedExceptionMessage) { try { ABI.downcallHandle(DUMMY_TARGET, desc, options); @@ -70,34 +75,34 @@ public void testIllegalLayouts(FunctionDescriptor desc, Linker.Option[] options, } } - @Test(dataProvider = "downcallOnlyOptions", - expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Not supported for upcall.*") + @ParameterizedTest + @MethodSource("downcallOnlyOptions") public void testIllegalUpcallOptions(Linker.Option downcallOnlyOption) { - ABI.upcallStub(DUMMY_TARGET_MH, FunctionDescriptor.ofVoid(), Arena.ofAuto(), downcallOnlyOption); + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> { + ABI.upcallStub(DUMMY_TARGET_MH, FunctionDescriptor.ofVoid(), Arena.ofAuto(), downcallOnlyOption); + }); + assertTrue(iae.getMessage().matches(".*Not supported for upcall.*")); } - @Test(dataProvider = "illegalCaptureState", - expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Unknown name.*") + @ParameterizedTest + @MethodSource("illegalCaptureState") + @DisabledOnOs(OS.WINDOWS) public void testIllegalCaptureState(String name) { - Linker.Option.captureCallState(name); + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + Linker.Option.captureCallState(name); + }); + assertTrue(e.getMessage().matches(".*Unknown name.*")); } // where - @DataProvider public static Object[][] illegalCaptureState() { - if (!IS_WINDOWS) { - return new Object[][]{ - { "GetLastError" }, - { "WSAGetLastError" }, - }; - } - return new Object[][]{}; + return new Object[][]{ + { "GetLastError" }, + { "WSAGetLastError" }, + }; } - @DataProvider public static Object[][] downcallOnlyOptions() { return new Object[][]{ { Linker.Option.firstVariadicArg(0) }, @@ -106,7 +111,6 @@ public static Object[][] downcallOnlyOptions() { }; } - @DataProvider public static Object[][] types() { Linker.Option[] NO_OPTIONS = new Linker.Option[0]; List cases = new ArrayList<>(Arrays.asList(new Object[][]{ diff --git a/test/jdk/java/foreign/TestIntrinsics.java b/test/jdk/java/foreign/TestIntrinsics.java index 5024a9094971..5a940577f803 100644 --- a/test/jdk/java/foreign/TestIntrinsics.java +++ b/test/jdk/java/foreign/TestIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm/native + * @run junit/othervm/native * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * --enable-native-access=ALL-UNNAMED * -Xbatch @@ -39,13 +39,17 @@ import java.util.List; import java.lang.foreign.MemoryLayout; -import org.testng.annotations.*; import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.invoke.MethodType.methodType; import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestIntrinsics extends NativeTestHelper { static final Linker abi = Linker.nativeLinker(); @@ -57,14 +61,14 @@ private interface RunnableX { void run() throws Throwable; } - @Test(dataProvider = "tests") + @ParameterizedTest + @MethodSource("tests") public void testIntrinsics(RunnableX test) throws Throwable { for (int i = 0; i < 20_000; i++) { test.run(); } } - @DataProvider public Object[][] tests() { List testsList = new ArrayList<>(); @@ -74,7 +78,7 @@ interface AddTest { AddTest tests = (mh, expectedResult, args) -> testsList.add(() -> { Object actual = mh.invokeWithArguments(args); - assertEquals(actual, expectedResult); + assertEquals(expectedResult, actual); }); interface AddIdentity { diff --git a/test/jdk/java/foreign/TestLargeSegmentCopy.java b/test/jdk/java/foreign/TestLargeSegmentCopy.java index c1508e592c3d..8b7ad35f590e 100644 --- a/test/jdk/java/foreign/TestLargeSegmentCopy.java +++ b/test/jdk/java/foreign/TestLargeSegmentCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,16 +26,17 @@ * @test * @requires sun.arch.data.model == "64" * @bug 8292851 - * @run testng/othervm -Xmx4G TestLargeSegmentCopy + * @run junit/othervm -Xmx4G TestLargeSegmentCopy */ -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import static java.lang.foreign.ValueLayout.JAVA_LONG; +import org.junit.jupiter.api.Test; + public class TestLargeSegmentCopy { @Test diff --git a/test/jdk/java/foreign/TestLayoutPaths.java b/test/jdk/java/foreign/TestLayoutPaths.java index 6729fbf82368..e4b5c116fc12 100644 --- a/test/jdk/java/foreign/TestLayoutPaths.java +++ b/test/jdk/java/foreign/TestLayoutPaths.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,12 @@ /* * @test - * @run testng TestLayoutPaths + * @run junit TestLayoutPaths */ import java.lang.foreign.*; import java.lang.foreign.MemoryLayout.PathElement; -import org.testng.annotations.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; @@ -46,84 +45,116 @@ import static java.lang.foreign.MemoryLayout.PathElement.sequenceElement; import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_SHORT; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestLayoutPaths { - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadByteSelectFromSeq() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(groupElement("foo")); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(groupElement("foo")); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadByteSelectFromStruct() { GroupLayout g = MemoryLayout.structLayout(JAVA_INT); - g.byteOffset(sequenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + g.byteOffset(sequenceElement()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadByteSelectFromValue() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(sequenceElement(), sequenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(sequenceElement(), sequenceElement()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testUnknownByteStructField() { GroupLayout g = MemoryLayout.structLayout(JAVA_INT); - g.byteOffset(groupElement("foo")); + assertThrows(IllegalArgumentException.class, () -> { + g.byteOffset(groupElement("foo")); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testTooBigGroupElementIndex() { GroupLayout g = MemoryLayout.structLayout(JAVA_INT); - g.byteOffset(groupElement(1)); + assertThrows(IllegalArgumentException.class, () -> { + g.byteOffset(groupElement(1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNegativeGroupElementIndex() { GroupLayout g = MemoryLayout.structLayout(JAVA_INT); - g.byteOffset(groupElement(-1)); + assertThrows(IllegalArgumentException.class, () -> { + g.byteOffset(groupElement(-1)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testByteOutOfBoundsSeqIndex() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(sequenceElement(6)); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(sequenceElement(6)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNegativeSeqIndex() { - sequenceElement(-2); + assertThrows(IllegalArgumentException.class, () -> { + sequenceElement(-2); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testByteNegativeSeqIndex() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(sequenceElement(-2)); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(sequenceElement(-2)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testOutOfBoundsSeqRange() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(sequenceElement(6, 2)); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(sequenceElement(6, 2)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNegativeSeqRange() { - sequenceElement(-2, 2); + assertThrows(IllegalArgumentException.class, () -> { + sequenceElement(-2, 2); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testByteNegativeSeqRange() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT); - seq.byteOffset(sequenceElement(-2, 2)); + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffset(sequenceElement(-2, 2)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testIncompleteAccess() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT)); - seq.varHandle(sequenceElement()); + assertThrows(IllegalArgumentException.class, () -> { + seq.varHandle(sequenceElement()); + }); } @Test @@ -132,10 +163,12 @@ public void testByteOffsetHandleRange() { seq.byteOffsetHandle(sequenceElement(0, 1)); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testByteOffsetHandleBadRange() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT)); - seq.byteOffsetHandle(sequenceElement(5, 1)); // invalid range (starting position is outside the sequence) + assertThrows(IllegalArgumentException.class, () -> { + seq.byteOffsetHandle(sequenceElement(5, 1)); // invalid range (starting position is outside the sequence) + }); } @Test @@ -143,23 +176,23 @@ public void testBadAlignmentOfRoot() { MemoryLayout struct = MemoryLayout.structLayout( JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN).withName("x")); - assertEquals(struct.byteAlignment(), 4); + assertEquals(4, struct.byteAlignment()); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(struct.byteSize() + 2, struct.byteAlignment()).asSlice(2); - assertEquals(seg.address() % JAVA_SHORT.byteAlignment(), 0); // should be aligned - assertNotEquals(seg.address() % struct.byteAlignment(), 0); // should not be aligned + assertEquals(0, seg.address() % JAVA_SHORT.byteAlignment()); // should be aligned + assertNotEquals(0, seg.address() % struct.byteAlignment()); // should not be aligned String expectedMessage = "Target offset 0 is incompatible with alignment constraint " + struct.byteAlignment() + " (of [i4s2(x)]) for segment MemorySegment"; VarHandle vhX = struct.varHandle(groupElement("x")); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> { + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> { vhX.set(seg, 0L, (short) 42); }); assertTrue(iae.getMessage().startsWith(expectedMessage)); MethodHandle sliceX = struct.sliceHandle(groupElement("x")); - iae = expectThrows(IllegalArgumentException.class, () -> { + iae = assertThrows(IllegalArgumentException.class, () -> { MemorySegment slice = (MemorySegment) sliceX.invokeExact(seg, 0L); }); assertTrue(iae.getMessage().startsWith(expectedMessage)); @@ -175,9 +208,9 @@ public void testWrongTypeRoot() { var expectedMessage = "Bad layout path: attempting to select a sequence element from a non-sequence layout: [i4i4]"; - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> struct.select(PathElement.sequenceElement())); - assertEquals(iae.getMessage(), expectedMessage); + assertEquals(expectedMessage, iae.getMessage()); } @Test @@ -195,11 +228,11 @@ public void testWrongTypeEnclosing() { "[2:[i4(3a)i4(3b)](2)](1), selected from: " + "[[2:[i4(3a)i4(3b)](2)](1)](0)"; - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> struct.select(PathElement.groupElement("1"), PathElement.sequenceElement(), PathElement.sequenceElement())); - assertEquals(iae.getMessage(), expectedMessage); + assertEquals(expectedMessage, iae.getMessage()); } @Test @@ -229,7 +262,8 @@ public void testBadSequencePathInSelect() { } } - @Test(dataProvider = "groupSelectors") + @ParameterizedTest + @MethodSource("groupSelectors") public void testStructPaths(IntFunction groupSelector) { long[] offsets = { 0, 1, 3, 7 }; GroupLayout g = MemoryLayout.structLayout( @@ -250,11 +284,12 @@ public void testStructPaths(IntFunction groupSelector) { for (int i = 0 ; i < 4 ; i++) { long byteOffset = g.byteOffset(groupSelector.apply(i)); - assertEquals(offsets[i], byteOffset); + assertEquals(byteOffset, offsets[i]); } } - @Test(dataProvider = "groupSelectors") + @ParameterizedTest + @MethodSource("groupSelectors") public void testUnionPaths(IntFunction groupSelector) { long[] offsets = { 0, 0, 0, 0 }; GroupLayout g = MemoryLayout.unionLayout( @@ -275,11 +310,10 @@ public void testUnionPaths(IntFunction groupSelector) { for (int i = 0 ; i < 4 ; i++) { long byteOffset = g.byteOffset(groupSelector.apply(i)); - assertEquals(offsets[i], byteOffset); + assertEquals(byteOffset, offsets[i]); } } - @DataProvider public static Object[][] groupSelectors() { return new Object[][] { { (IntFunction) PathElement::groupElement }, // by index @@ -301,20 +335,22 @@ public void testSequencePaths() { for (int i = 0 ; i < 4 ; i++) { long byteOffset = g.byteOffset(sequenceElement(i)); - assertEquals(offsets[i], byteOffset); + assertEquals(byteOffset, offsets[i]); } } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testOffsetHandle(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MethodHandle byteOffsetHandle = layout.byteOffsetHandle(pathElements); byteOffsetHandle = byteOffsetHandle.asSpreader(long[].class, indexes.length); long actualByteOffset = (long) byteOffsetHandle.invokeExact(0L, indexes); - assertEquals(actualByteOffset, expectedByteOffset); + assertEquals(expectedByteOffset, actualByteOffset); } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testOffsetHandleOOBIndex(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { int[] badIndices = { -1, 10 }; @@ -332,15 +368,19 @@ public void testOffsetHandleOOBIndex(MemoryLayout layout, PathElement[] pathElem } } - @Test(dataProvider = "testLayouts", expectedExceptions = ArithmeticException.class) + @ParameterizedTest + @MethodSource("testLayouts") public void testOffsetHandleOverflow(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MethodHandle byteOffsetHandle = layout.byteOffsetHandle(pathElements); - byteOffsetHandle = byteOffsetHandle.asSpreader(long[].class, indexes.length); - byteOffsetHandle.invoke(Long.MAX_VALUE, indexes); + MethodHandle finalHandle = byteOffsetHandle.asSpreader(long[].class, indexes.length); + assertThrows(ArithmeticException.class, () -> { + finalHandle.invoke(Long.MAX_VALUE, indexes); + }); } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testVarHandleBadSegment(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MemoryLayout seqLayout = MemoryLayout.sequenceLayout(10, layout); @@ -357,7 +397,8 @@ public void testVarHandleBadSegment(MemoryLayout layout, PathElement[] pathEleme assertThrows(IndexOutOfBoundsException.class, () -> getter_handle.invoke(segment, 0L, seqIndexes)); } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testSliceHandleBadSegment(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MemoryLayout seqLayout = MemoryLayout.sequenceLayout(10, layout); @@ -373,7 +414,8 @@ public void testSliceHandleBadSegment(MemoryLayout layout, PathElement[] pathEle assertThrows(IndexOutOfBoundsException.class, () -> getter_handle.invoke(segment, 0L, seqIndexes)); } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testArrayElementVarHandleBadSegment(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MemoryLayout seqLayout = MemoryLayout.sequenceLayout(10, layout); @@ -395,46 +437,45 @@ public void testArrayElementVarHandleBadSegment(MemoryLayout layout, PathElement public void testHashCodeCollision() { PathElement sequenceElement = PathElement.sequenceElement(); PathElement dereferenceElement = PathElement.dereferenceElement(); - assertNotEquals(sequenceElement.hashCode(), dereferenceElement.hashCode()); + assertNotEquals(dereferenceElement.hashCode(), sequenceElement.hashCode()); } @Test public void testGroupElementIndexToString() { PathElement e = PathElement.groupElement(2); - assertEquals(e.toString(), "groupElement(2)"); + assertEquals("groupElement(2)", e.toString()); } @Test public void testGroupElementNameToString() { PathElement e = PathElement.groupElement("x"); - assertEquals(e.toString(), "groupElement(\"x\")"); + assertEquals("groupElement(\"x\")", e.toString()); } @Test public void testSequenceElementToString() { PathElement e = PathElement.sequenceElement(); - assertEquals(e.toString(), "sequenceElement()"); + assertEquals("sequenceElement()", e.toString()); } @Test public void testSequenceElementIndexToString() { PathElement e = PathElement.sequenceElement(2); - assertEquals(e.toString(), "sequenceElement(2)"); + assertEquals("sequenceElement(2)", e.toString()); } @Test public void testSequenceElementRangeToString() { PathElement e = PathElement.sequenceElement(2, 4); - assertEquals(e.toString(), "sequenceElement(2, 4)"); + assertEquals("sequenceElement(2, 4)", e.toString()); } @Test public void testDerefereceElementToString() { PathElement e = PathElement.dereferenceElement(); - assertEquals(e.toString(), "dereferenceElement()"); + assertEquals("dereferenceElement()", e.toString()); } - @DataProvider public static Object[][] testLayouts() { List testCases = new ArrayList<>(); @@ -510,7 +551,8 @@ public static Object[][] testLayouts() { return testCases.toArray(Object[][]::new); } - @Test(dataProvider = "testLayouts") + @ParameterizedTest + @MethodSource("testLayouts") public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, long[] indexes, long expectedByteOffset) throws Throwable { MemoryLayout selected = layout.select(pathElements); @@ -520,8 +562,8 @@ public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, lon try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(layout); MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, 0L, indexes); - assertEquals(slice.address() - segment.address(), expectedByteOffset); - assertEquals(slice.byteSize(), selected.byteSize()); + assertEquals(expectedByteOffset, slice.address() - segment.address()); + assertEquals(selected.byteSize(), slice.byteSize()); } } diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index 2606e0481b32..730d26fedc06 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestLayouts + * @run junit TestLayouts */ import java.lang.foreign.*; @@ -36,19 +36,28 @@ import java.util.function.LongFunction; import java.util.stream.Stream; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestLayouts { - @Test(dataProvider = "badAlignments", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("layoutsAndBadAlignments") public void testBadLayoutAlignment(MemoryLayout layout, long alignment) { - layout.withByteAlignment(alignment); + assertThrows(IllegalArgumentException.class, () -> { + layout.withByteAlignment(alignment); + }); } - @Test(dataProvider = "basicLayoutsAndAddressAndGroups") + @ParameterizedTest + @MethodSource("basicLayoutsAndAddressAndGroups") public void testEqualities(MemoryLayout layout) { // Use another Type @@ -110,26 +119,36 @@ public void testIndexedSequencePath() { } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadBoundSequenceLayoutResize() { SequenceLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT); - seq.withElementCount(-1); + assertThrows(IllegalArgumentException.class, () -> { + seq.withElementCount(-1); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testReshape() { SequenceLayout layout = MemoryLayout.sequenceLayout(10, JAVA_INT); - layout.reshape(); + assertThrows(IllegalArgumentException.class, () -> { + layout.reshape(); + }); } - @Test(dataProvider = "basicLayoutsAndAddressAndGroups", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("basicLayoutsAndAddressAndGroups") public void testGroupIllegalAlignmentNotPowerOfTwo(MemoryLayout layout) { - layout.withByteAlignment(9); + assertThrows(IllegalArgumentException.class, () -> { + layout.withByteAlignment(9); + }); } - @Test(dataProvider = "basicLayoutsAndAddressAndGroups", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("basicLayoutsAndAddressAndGroups") public void testGroupIllegalAlignmentNotGreaterOrEqualTo1(MemoryLayout layout) { - layout.withByteAlignment(0); + assertThrows(IllegalArgumentException.class, () -> { + layout.withByteAlignment(0); + }); } @Test @@ -137,18 +156,18 @@ public void testEqualsPadding() { PaddingLayout paddingLayout = MemoryLayout.paddingLayout(2); testEqualities(paddingLayout); PaddingLayout paddingLayout2 = MemoryLayout.paddingLayout(4); - assertNotEquals(paddingLayout, paddingLayout2); + assertNotEquals(paddingLayout2, paddingLayout); } @Test public void testEmptyGroup() { MemoryLayout struct = MemoryLayout.structLayout(); - assertEquals(struct.byteSize(), 0); - assertEquals(struct.byteAlignment(), 1); + assertEquals(0, struct.byteSize()); + assertEquals(1, struct.byteAlignment()); MemoryLayout union = MemoryLayout.unionLayout(); - assertEquals(union.byteSize(), 0); - assertEquals(union.byteAlignment(), 1); + assertEquals(0, union.byteSize()); + assertEquals(1, union.byteAlignment()); } @Test @@ -160,27 +179,30 @@ public void testStructSizeAndAlign() { ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG ); - assertEquals(struct.byteSize(), 1 + 1 + 2 + 4 + 8); - assertEquals(struct.byteAlignment(), 8); + assertEquals(1 + 1 + 2 + 4 + 8, struct.byteSize()); + assertEquals(8, struct.byteAlignment()); } - @Test(dataProvider="basicLayouts") + @ParameterizedTest + @MethodSource("basicLayouts") public void testPaddingNoAlign(MemoryLayout layout) { - assertEquals(MemoryLayout.paddingLayout(layout.byteSize()).byteAlignment(), 1); + assertEquals(1, MemoryLayout.paddingLayout(layout.byteSize()).byteAlignment()); } - @Test(dataProvider="basicLayouts") + @ParameterizedTest + @MethodSource("basicLayouts") public void testStructPaddingAndAlign(MemoryLayout layout) { MemoryLayout struct = MemoryLayout.structLayout( layout, MemoryLayout.paddingLayout(16 - layout.byteSize())); - assertEquals(struct.byteAlignment(), layout.byteAlignment()); + assertEquals(layout.byteAlignment(), struct.byteAlignment()); } - @Test(dataProvider="basicLayouts") + @ParameterizedTest + @MethodSource("basicLayouts") public void testUnionPaddingAndAlign(MemoryLayout layout) { MemoryLayout struct = MemoryLayout.unionLayout( layout, MemoryLayout.paddingLayout(16 - layout.byteSize())); - assertEquals(struct.byteAlignment(), layout.byteAlignment()); + assertEquals(layout.byteAlignment(), struct.byteAlignment()); } @Test @@ -191,8 +213,8 @@ public void testUnionSizeAndAlign() { ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG ); - assertEquals(struct.byteSize(), 8); - assertEquals(struct.byteAlignment(), 8); + assertEquals(8, struct.byteSize()); + assertEquals(8, struct.byteAlignment()); } @Test @@ -220,16 +242,16 @@ public void testSequenceOverflow() { @Test public void testSequenceLayoutWithZeroLength() { SequenceLayout layout = MemoryLayout.sequenceLayout(0, JAVA_INT); - assertEquals(layout.toString().toLowerCase(Locale.ROOT), "[0:i4]"); + assertEquals("[0:i4]", layout.toString().toLowerCase(Locale.ROOT)); SequenceLayout nested = MemoryLayout.sequenceLayout(0, layout); - assertEquals(nested.toString().toLowerCase(Locale.ROOT), "[0:[0:i4]]"); + assertEquals("[0:[0:i4]]", nested.toString().toLowerCase(Locale.ROOT)); SequenceLayout layout2 = MemoryLayout.sequenceLayout(0, JAVA_INT); - assertEquals(layout, layout2); + assertEquals(layout2, layout); SequenceLayout nested2 = MemoryLayout.sequenceLayout(0, layout2); - assertEquals(nested, nested2); + assertEquals(nested2, nested); } @Test @@ -246,14 +268,14 @@ public void testStructOverflow() { @Test public void testPadding() { var padding = MemoryLayout.paddingLayout(1); - assertEquals(padding.byteAlignment(), 1); + assertEquals(1, padding.byteAlignment()); } @Test public void testPaddingInStruct() { var padding = MemoryLayout.paddingLayout(1); var struct = MemoryLayout.structLayout(padding); - assertEquals(struct.byteAlignment(), 1); + assertEquals(1, struct.byteAlignment()); } @Test @@ -273,31 +295,34 @@ public void testStructToString() { for (ByteOrder order : List.of(ByteOrder.LITTLE_ENDIAN, ByteOrder.BIG_ENDIAN)) { String intRepresentation = (order == ByteOrder.LITTLE_ENDIAN ? "i" : "I"); StructLayout padding = MemoryLayout.structLayout(JAVA_INT.withOrder(order)).withName("struct"); - assertEquals(padding.toString(), "[" + intRepresentation + "4](struct)"); + assertEquals("[" + intRepresentation + "4](struct)", padding.toString()); var toStringUnaligned = padding.withByteAlignment(8).toString(); - assertEquals(toStringUnaligned, "8%[" + intRepresentation + "4](struct)"); + assertEquals("8%[" + intRepresentation + "4](struct)", toStringUnaligned); } } - @Test(dataProvider = "layoutKinds") + @ParameterizedTest + @MethodSource("layoutsKinds") public void testPadding(LayoutKind kind) { - assertEquals(kind == LayoutKind.PADDING, kind.layout instanceof PaddingLayout); + assertEquals(kind.layout instanceof PaddingLayout, kind == LayoutKind.PADDING); } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testAlignmentString(MemoryLayout layout, long byteAlign) { long[] alignments = { 1, 2, 4, 8, 16 }; for (long a : alignments) { if (layout.byteAlignment() == byteAlign) { assertFalse(layout.toString().contains("%")); if (a >= layout.byteAlignment()) { - assertEquals(layout.withByteAlignment(a).toString().contains("%"), a != byteAlign); + assertEquals(a != byteAlign, layout.withByteAlignment(a).toString().contains("%")); } } } } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadByteAlignment(MemoryLayout layout, long byteAlign) { long[] alignments = { 1, 2, 4, 8, 16 }; for (long a : alignments) { @@ -307,15 +332,17 @@ public void testBadByteAlignment(MemoryLayout layout, long byteAlign) { } } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadSequenceElementAlignmentTooBig(MemoryLayout layout, long byteAlign) { MemoryLayout elementLayout = layout.withByteAlignment(nextPowerOfTwo(layout.byteSize() * 2)); // hyper-align - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> MemoryLayout.sequenceLayout(1, elementLayout)); - assertEquals(iae.getMessage(), "Element layout size is not multiple of alignment"); + assertEquals("Element layout size is not multiple of alignment", iae.getMessage()); } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadSequenceElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) { boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0; try { @@ -326,7 +353,8 @@ public void testBadSequenceElementSizeNotMultipleOfAlignment(MemoryLayout layout } } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadSpliteratorElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) { boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0; try (Arena arena = Arena.ofConfined()) { @@ -338,7 +366,8 @@ public void testBadSpliteratorElementSizeNotMultipleOfAlignment(MemoryLayout lay } } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadElementsElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) { boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0; try (Arena arena = Arena.ofConfined()) { @@ -350,18 +379,21 @@ public void testBadElementsElementSizeNotMultipleOfAlignment(MemoryLayout layout } } - @Test(dataProvider="layoutsAndAlignments") + @ParameterizedTest + @MethodSource("layoutsAndAlignments") public void testBadStruct(MemoryLayout layout, long byteAlign) { MemoryLayout elementLayout = layout.withByteAlignment(nextPowerOfTwo(layout.byteSize() * 2)); // hyper-align - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> MemoryLayout.structLayout(elementLayout, elementLayout)); assertTrue(iae.getMessage().contains("Invalid alignment constraint for member layout")); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testSequenceElement() { - // Step must be != 0 - PathElement.sequenceElement(3, 0); + assertThrows(IllegalArgumentException.class, () -> { + // Step must be != 0 + PathElement.sequenceElement(3, 0); + }); } @Test @@ -373,29 +405,36 @@ public void testVarHandleCaching() { assertNotSame(ADDRESS.withTargetLayout(JAVA_INT).varHandle(), ADDRESS.varHandle()); } - @Test(expectedExceptions=IllegalArgumentException.class, - expectedExceptionsMessageRegExp=".*offset is negative.*") + @Test public void testScaleNegativeOffset() { - JAVA_INT.scale(-1, 0); + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + JAVA_INT.scale(-1, 0); + }); + assertTrue(e.getMessage().matches(".*offset is negative.*")); } - @Test(expectedExceptions=IllegalArgumentException.class, - expectedExceptionsMessageRegExp=".*index is negative.*") + @Test public void testScaleNegativeIndex() { - JAVA_INT.scale(0, -1); + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + JAVA_INT.scale(0, -1); + }); + assertTrue(e.getMessage().matches(".*index is negative.*")); } - @Test(expectedExceptions=ArithmeticException.class) + @Test public void testScaleAddOverflow() { - JAVA_INT.scale(Long.MAX_VALUE, 1); + assertThrows(ArithmeticException.class, () -> { + JAVA_INT.scale(Long.MAX_VALUE, 1); + }); } - @Test(expectedExceptions=ArithmeticException.class) + @Test public void testScaleMultiplyOverflow() { - JAVA_INT.scale(0, Long.MAX_VALUE); + assertThrows(ArithmeticException.class, () -> { + JAVA_INT.scale(0, Long.MAX_VALUE); + }); } - @DataProvider(name = "badAlignments") public Object[][] layoutsAndBadAlignments() { LayoutKind[] layoutKinds = LayoutKind.values(); Object[][] values = new Object[layoutKinds.length * 2][2]; @@ -406,7 +445,6 @@ public Object[][] layoutsAndBadAlignments() { return values; } - @DataProvider(name = "layoutKinds") public Object[][] layoutsKinds() { return Stream.of(LayoutKind.values()) .map(lk -> new Object[] { lk }) @@ -454,28 +492,24 @@ enum LayoutKind { } } - @DataProvider(name = "basicLayouts") public Object[][] basicLayouts() { return Stream.of(basicLayouts) .map(l -> new Object[] { l }) .toArray(Object[][]::new); } - @DataProvider(name = "basicLayoutsAndAddress") public Object[][] basicLayoutsAndAddress() { return Stream.concat(Stream.of(basicLayouts), Stream.of(ADDRESS)) .map(l -> new Object[] { l }) .toArray(Object[][]::new); } - @DataProvider(name = "basicLayoutsAndAddressAndGroups") public Object[][] basicLayoutsAndAddressAndGroups() { return Stream.concat(Stream.concat(Stream.of(basicLayouts), Stream.of(ADDRESS)), groupLayoutStream()) .map(l -> new Object[] { l }) .toArray(Object[][]::new); } - @DataProvider(name = "layoutsAndAlignments") public Object[][] layoutsAndAlignments() { List layoutsAndAlignments = new ArrayList<>(); int i = 0; @@ -505,14 +539,12 @@ public Object[][] layoutsAndAlignments() { return layoutsAndAlignments.toArray(Object[][]::new); } - @DataProvider(name = "groupLayouts") public Object[][] groupLayouts() { return groupLayoutStream() .map(l -> new Object[] { l }) .toArray(Object[][]::new); } - @DataProvider(name = "validCarriers") public Object[][] validCarriers() { return Stream.of( boolean.class, diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java index 902b938ac62a..734361496724 100644 --- a/test/jdk/java/foreign/TestLinker.java +++ b/test/jdk/java/foreign/TestLinker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,12 @@ /* * @test * @modules java.base/jdk.internal.foreign java.base/jdk.internal.foreign.abi.fallback - * @run testng TestLinker - * @run testng/othervm TestLinker + * @run junit TestLinker + * @run junit/othervm TestLinker */ import jdk.internal.foreign.CABI; import jdk.internal.foreign.abi.fallback.FallbackLinker; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; @@ -47,15 +45,22 @@ import static java.lang.foreign.MemoryLayout.*; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestLinker extends NativeTestHelper { static final boolean IS_FALLBACK_LINKER = CABI.current() == CABI.FALLBACK; record LinkRequest(FunctionDescriptor descriptor, Linker.Option... options) {} - @Test(dataProvider = "notSameCases") + @ParameterizedTest + @MethodSource("notSameCases") public void testLinkerOptionsCache(LinkRequest l1, LinkRequest l2) { Linker linker = Linker.nativeLinker(); MethodHandle mh1 = linker.downcallHandle(l1.descriptor(), l1.options()); @@ -64,7 +69,6 @@ public void testLinkerOptionsCache(LinkRequest l1, LinkRequest l2) { assertNotSame(mh1, mh2); } - @DataProvider public static Object[][] notSameCases() { FunctionDescriptor fd_II_V = FunctionDescriptor.ofVoid(C_INT, C_INT); return new Object[][]{ @@ -74,7 +78,8 @@ public static Object[][] notSameCases() { }; } - @Test(dataProvider = "namedDescriptors") + @ParameterizedTest + @MethodSource("namedDescriptors") public void testNamedLinkerCache(FunctionDescriptor f1, FunctionDescriptor f2) { Linker linker = Linker.nativeLinker(); MethodHandle mh1 = linker.downcallHandle(f1); @@ -83,7 +88,6 @@ public void testNamedLinkerCache(FunctionDescriptor f1, FunctionDescriptor f2) { assertSame(mh1, mh2); } - @DataProvider public static Object[][] namedDescriptors() { List cases = new ArrayList<>(Arrays.asList(new Object[][]{ { FunctionDescriptor.ofVoid(C_INT), @@ -120,7 +124,6 @@ public static Object[][] namedDescriptors() { return cases.toArray(Object[][]::new); } - @DataProvider public static Object[][] invalidIndexCases() { return new Object[][]{ { -1, }, @@ -128,22 +131,27 @@ public static Object[][] invalidIndexCases() { }; } - @Test(dataProvider = "invalidIndexCases", - expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*not in bounds for descriptor.*") + @ParameterizedTest + @MethodSource("invalidIndexCases") public void testInvalidOption(int invalidIndex) { Linker.Option option = Linker.Option.firstVariadicArg(invalidIndex); FunctionDescriptor desc = FunctionDescriptor.ofVoid(); - Linker.nativeLinker().downcallHandle(desc, option); // throws + IllegalArgumentException e =assertThrows(IllegalArgumentException.class, () -> { + Linker.nativeLinker().downcallHandle(desc, option); + }); + assertTrue(e.getMessage().matches(".*not in bounds for descriptor.*")); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Unknown name.*") + @Test public void testInvalidPreservedValueName() { - Linker.Option.captureCallState("foo"); // throws + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + Linker.Option.captureCallState("foo"); + }); + assertTrue(e.getMessage().matches(".*Unknown name.*")); } - @Test(dataProvider = "canonicalTypeNames") + @ParameterizedTest + @MethodSource("canonicalTypeNames") public void testCanonicalLayouts(String typeName) { MemoryLayout layout = LINKER.canonicalLayouts().get(typeName); assertNotNull(layout); @@ -157,7 +165,7 @@ public void embeddedPaddingLayout() { StructLayout struct = MemoryLayout.structLayout(sequence); FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); Linker linker = Linker.nativeLinker(); - var x = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + var x = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); assertTrue(x.getMessage().contains("not supported because a sequence of a padding layout is not allowed")); } @@ -167,7 +175,7 @@ public void groupLayoutWithOnlyPadding() { StructLayout struct = MemoryLayout.structLayout(padding); FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); Linker linker = Linker.nativeLinker(); - var x = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + var x = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); assertTrue(x.getMessage().contains("is non-empty and only has padding layouts")); } @@ -180,9 +188,8 @@ public void interwovenPadding() { 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 " + struct); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals( "The padding layout x2 was preceded by another padding layout x1 in " + struct, e.getMessage()); } @Test @@ -198,9 +205,8 @@ public void stackedPadding() { 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 " + struct); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals( "The padding layout x2 was preceded by another padding layout x1 in " + struct, e.getMessage()); } @Test @@ -208,8 +214,8 @@ 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 " + union); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals("Superfluous padding x3 in " + union, e.getMessage()); } @Test @@ -217,8 +223,8 @@ 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 " + union); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals("Superfluous padding x4 in " + union, e.getMessage()); } @Test @@ -226,8 +232,8 @@ 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 '" + union + "' has unexpected size: 5 != 4"); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals("Layout '" + union + "' has unexpected size: 5 != 4", e.getMessage()); } @Test @@ -239,8 +245,8 @@ public void paddingUnionSeveral() { 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 " + union); + var e = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals("More than one padding in " + union, e.getMessage()); } @Test @@ -253,14 +259,13 @@ public void sequenceOfZeroElements() { var fd = FunctionDescriptor.of(struct8a8, struct8a8, struct8a8); if (linker.getClass().equals(FallbackLinker.class)) { // The fallback linker does not support empty layouts (FFI_BAD_TYPEDEF) - var iae = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + var iae = assertThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); assertTrue(iae.getMessage().contains("is empty")); } else { linker.downcallHandle(fd); } } - @DataProvider public static Object[][] canonicalTypeNames() { return new Object[][]{ { "bool" }, @@ -277,8 +282,10 @@ public static Object[][] canonicalTypeNames() { }; } - @Test(expectedExceptions=UnsupportedOperationException.class) + @Test public void testCanonicalLayoutsUnmodifiable() { - LINKER.canonicalLayouts().put("asdf", C_INT); + assertThrows(UnsupportedOperationException.class, () -> { + LINKER.canonicalLayouts().put("asdf", C_INT); + }); } } diff --git a/test/jdk/java/foreign/TestMappedHandshake.java b/test/jdk/java/foreign/TestMappedHandshake.java index 46fb4fb45fb9..262518d674bc 100644 --- a/test/jdk/java/foreign/TestMappedHandshake.java +++ b/test/jdk/java/foreign/TestMappedHandshake.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,10 @@ * @requires vm.flavor != "zero" * @modules java.base/jdk.internal.vm.annotation java.base/jdk.internal.misc * @key randomness - * @run testng/othervm TestMappedHandshake - * @run testng/othervm -Xint TestMappedHandshake - * @run testng/othervm -XX:TieredStopAtLevel=1 TestMappedHandshake - * @run testng/othervm -XX:-TieredCompilation TestMappedHandshake + * @run junit/othervm TestMappedHandshake + * @run junit/othervm -Xint TestMappedHandshake + * @run junit/othervm -XX:TieredStopAtLevel=1 TestMappedHandshake + * @run junit/othervm -XX:-TieredCompilation TestMappedHandshake */ import java.io.File; @@ -44,9 +44,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.testng.annotations.Test; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestMappedHandshake { diff --git a/test/jdk/java/foreign/TestMatrix.java b/test/jdk/java/foreign/TestMatrix.java index 4b2885da7ce0..befeddee6e47 100644 --- a/test/jdk/java/foreign/TestMatrix.java +++ b/test/jdk/java/foreign/TestMatrix.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -46,7 +46,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -57,7 +57,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -68,7 +68,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -79,7 +79,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * TestDowncallScope @@ -89,7 +89,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * TestDowncallScope @@ -99,7 +99,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * TestDowncallStack @@ -109,7 +109,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * TestDowncallStack @@ -119,7 +119,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -130,7 +130,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -141,7 +141,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -152,7 +152,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -163,7 +163,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -174,7 +174,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -185,7 +185,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -196,7 +196,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -207,7 +207,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -218,7 +218,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false @@ -229,7 +229,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -240,7 +240,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -252,7 +252,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper * - * @run testng/othervm/native/manual + * @run junit/othervm/native/manual * --enable-native-access=ALL-UNNAMED * TestVarArgs */ diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index ded9be1c085d..05f0ea3c5918 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * 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,10 @@ /* * @test - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess */ import java.lang.foreign.*; @@ -36,42 +36,51 @@ import java.nio.ByteOrder; import java.util.function.Function; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMemoryAccess { - @Test(dataProvider = "elements") + @ParameterizedTest + @MethodSource("createData") public void testAccess(Function viewFactory, ValueLayout elemLayout, Checker checker) { ValueLayout layout = elemLayout.withName("elem"); testAccessInternal(viewFactory, layout, layout.varHandle(), checker); } - @Test(dataProvider = "elements") + @ParameterizedTest + @MethodSource("createData") public void testPaddedAccessByName(Function viewFactory, MemoryLayout elemLayout, Checker checker) { GroupLayout layout = MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem")); testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.groupElement("elem")), checker); } - @Test(dataProvider = "elements") + @ParameterizedTest + @MethodSource("createData") public void testPaddedAccessByIndexSeq(Function viewFactory, MemoryLayout elemLayout, Checker checker) { SequenceLayout layout = MemoryLayout.sequenceLayout(2, elemLayout); testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.sequenceElement(1)), checker); } - @Test(dataProvider = "arrayElements") + @ParameterizedTest + @MethodSource("createArrayData") public void testArrayAccess(Function viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, elemLayout.withName("elem")); testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement()), checker); } - @Test(dataProvider = "arrayElements") + @ParameterizedTest + @MethodSource("createArrayData") public void testPaddedArrayAccessByName(Function viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem"))); testArrayAccessInternal(viewFactory, seq, seq.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("elem")), checker); } - @Test(dataProvider = "arrayElements") + @ParameterizedTest + @MethodSource("createArrayData") public void testPaddedArrayAccessByIndexSeq(Function viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout)); testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(1)), checker); @@ -143,7 +152,8 @@ private void testArrayAccessInternal(Function view } } - @Test(dataProvider = "matrixElements") + @ParameterizedTest + @MethodSource("createMatrixData") public void testMatrixAccess(Function viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, elemLayout.withName("elem"))); @@ -151,7 +161,8 @@ public void testMatrixAccess(Function viewFactory, PathElement.sequenceElement(), PathElement.sequenceElement()), checker); } - @Test(dataProvider = "matrixElements") + @ParameterizedTest + @MethodSource("createMatrixData") public void testPaddedMatrixAccessByName(Function viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem")))); @@ -161,7 +172,8 @@ public void testPaddedMatrixAccessByName(Function checker); } - @Test(dataProvider = "matrixElements") + @ParameterizedTest + @MethodSource("createMatrixData") public void testPaddedMatrixAccessByIndexSeq(Function viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout))); @@ -211,7 +223,6 @@ private void testMatrixAccessInternal(Function vie static Function ID = Function.identity(); static Function IMMUTABLE = MemorySegment::asReadOnly; - @DataProvider(name = "elements") public Object[][] createData() { return new Object[][] { //BE, RW @@ -288,7 +299,6 @@ interface Checker { }; } - @DataProvider(name = "arrayElements") public Object[][] createArrayData() { return new Object[][] { //BE, RW @@ -331,41 +341,40 @@ interface ArrayChecker { ArrayChecker BYTE = (handle, segment, i) -> { handle.set(segment, 0L, i, (byte)i); - assertEquals(i, (byte)handle.get(segment, 0L, i)); + assertEquals((byte)handle.get(segment, 0L, i), i); }; ArrayChecker SHORT = (handle, segment, i) -> { handle.set(segment, 0L, i, (short)i); - assertEquals(i, (short)handle.get(segment, 0L, i)); + assertEquals((short)handle.get(segment, 0L, i), i); }; ArrayChecker CHAR = (handle, segment, i) -> { handle.set(segment, 0L, i, (char)i); - assertEquals(i, (char)handle.get(segment, 0L, i)); + assertEquals((char)handle.get(segment, 0L, i), i); }; ArrayChecker INT = (handle, segment, i) -> { handle.set(segment, 0L, i, (int)i); - assertEquals(i, (int)handle.get(segment, 0L, i)); + assertEquals((int)handle.get(segment, 0L, i), i); }; ArrayChecker LONG = (handle, segment, i) -> { handle.set(segment, 0L, i, (long)i); - assertEquals(i, (long)handle.get(segment, 0L, i)); + assertEquals((long)handle.get(segment, 0L, i), i); }; ArrayChecker FLOAT = (handle, segment, i) -> { handle.set(segment, 0L, i, (float)i); - assertEquals((float)i, (float)handle.get(segment, 0L, i)); + assertEquals((float)handle.get(segment, 0L, i), (float)i); }; ArrayChecker DOUBLE = (handle, segment, i) -> { handle.set(segment, 0L, i, (double)i); - assertEquals((double)i, (double)handle.get(segment, 0L, i)); + assertEquals((double)handle.get(segment, 0L, i), (double)i); }; } - @DataProvider(name = "matrixElements") public Object[][] createMatrixData() { return new Object[][] { //BE, RW @@ -416,47 +425,47 @@ interface MatrixChecker { MatrixChecker BYTE = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (byte)(r + c)); - assertEquals(r + c, (byte)handle.get(segment, 0L, r, c)); + assertEquals((byte)handle.get(segment, 0L, r, c), r + c); }; MatrixChecker BOOLEAN = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (r + c) != 0); - assertEquals((r + c) != 0, (boolean)handle.get(segment, 0L, r, c)); + assertEquals((boolean)handle.get(segment, 0L, r, c), (r + c) != 0); }; MatrixChecker SHORT = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (short)(r + c)); - assertEquals(r + c, (short)handle.get(segment, 0L, r, c)); + assertEquals((short)handle.get(segment, 0L, r, c), r + c); }; MatrixChecker CHAR = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (char)(r + c)); - assertEquals(r + c, (char)handle.get(segment, 0L, r, c)); + assertEquals((char)handle.get(segment, 0L, r, c), r + c); }; MatrixChecker INT = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (int)(r + c)); - assertEquals(r + c, (int)handle.get(segment, 0L, r, c)); + assertEquals((int)handle.get(segment, 0L, r, c), r + c); }; MatrixChecker LONG = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, r + c); - assertEquals(r + c, (long)handle.get(segment, 0L, r, c)); + assertEquals((long)handle.get(segment, 0L, r, c), r + c); }; MatrixChecker ADDR = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, MemorySegment.ofAddress(r + c)); - assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, 0L, r, c)); + assertEquals((MemorySegment) handle.get(segment, 0L, r, c), MemorySegment.ofAddress(r + c)); }; MatrixChecker FLOAT = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (float)(r + c)); - assertEquals((float)(r + c), (float)handle.get(segment, 0L, r, c)); + assertEquals((float)handle.get(segment, 0L, r, c), (float)(r + c)); }; MatrixChecker DOUBLE = (handle, segment, r, c) -> { handle.set(segment, 0L, r, c, (double)(r + c)); - assertEquals((double)(r + c), (double)handle.get(segment, 0L, r, c)); + assertEquals((double)handle.get(segment, 0L, r, c), (double)(r + c)); }; } } diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index de1a17f5f113..617684f885d2 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * 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,8 +23,8 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_SEGMENT_FORCE_EXACT=true --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_SEGMENT_FORCE_EXACT=true --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance */ import java.lang.foreign.MemorySegment; @@ -33,10 +33,14 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; -import org.testng.annotations.*; -import org.testng.SkipException; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMemoryAccessInstance { static class Accessor { @@ -80,9 +84,9 @@ void test() { MemorySegment segment = arena.allocate(128, 1); ByteBuffer buffer = segment.asByteBuffer(); segmentSetter.set(segment, layout, 8, value); - assertEquals(bufferGetter.get(buffer, 8), value); + assertEquals(value, bufferGetter.get(buffer, 8)); bufferSetter.set(buffer, 8, value); - assertEquals(value, segmentGetter.get(segment, layout, 8)); + assertEquals(segmentGetter.get(segment, layout, 8), value); } } @@ -121,41 +125,45 @@ static Accessor of(L layout, X value, } } - @Test(dataProvider = "segmentAccessors") + @ParameterizedTest + @MethodSource("segmentAccessors") public void testSegmentAccess(String testName, Accessor accessor) { accessor.test(); } - @Test(dataProvider = "segmentAccessors") + @ParameterizedTest + @MethodSource("segmentAccessors") public void testSegmentAccessHyper(String testName, Accessor accessor) { - if (testName.contains("index")) { - accessor.testHyperAligned(); - } else { - throw new SkipException("Skipping"); - } + Assumptions.assumeTrue(testName.contains("index"), "Skipping"); + accessor.testHyperAligned(); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void badHeapSegmentSet() { long byteSize = ValueLayout.ADDRESS.byteSize(); Arena scope = Arena.ofAuto(); MemorySegment targetSegment = scope.allocate(byteSize, 1); MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); - targetSegment.set(ValueLayout.ADDRESS, 0, segment); // should throw + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + targetSegment.set(ValueLayout.ADDRESS, 0, segment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void badHeapSegmentSetAtIndex() { long byteSize = ValueLayout.ADDRESS.byteSize(); Arena scope = Arena.ofAuto(); MemorySegment targetSegment = scope.allocate(byteSize, 1); MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); - targetSegment.setAtIndex(ValueLayout.ADDRESS, 0, segment); // should throw + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + targetSegment.setAtIndex(ValueLayout.ADDRESS, 0, segment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } - @Test(dataProvider = "segmentAccessors") + @ParameterizedTest + @MethodSource("segmentAccessors") public void badAccessOverflowInIndexedAccess(String testName, Accessor accessor) { MemorySegment segment = MemorySegment.ofArray(new byte[100]); if (testName.contains("/index") && accessor.layout.byteSize() > 1) { @@ -164,7 +172,8 @@ public void badAccessOverflowInIndexedAccess(String t } } - @Test(dataProvider = "segmentAccessors") + @ParameterizedTest + @MethodSource("segmentAccessors") public void negativeOffset(String testName, Accessor accessor) { MemorySegment segment = MemorySegment.ofArray(new byte[100]); assertThrows(IndexOutOfBoundsException.class, () -> accessor.get(segment, -ValueLayout.JAVA_LONG.byteSize())); @@ -173,7 +182,6 @@ public void negativeOffset(String testName, Accessor< static final ByteOrder NE = ByteOrder.nativeOrder(); - @DataProvider(name = "segmentAccessors") static Object[][] segmentAccessors() { return new Object[][]{ diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index 19f9f576ab2e..a80b7a98f150 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestMemoryAlignment + * @run junit TestMemoryAlignment */ import java.io.File; @@ -46,18 +46,23 @@ import java.util.stream.LongStream; import java.util.stream.Stream; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMemoryAlignment { - @Test(dataProvider = "alignments") + @ParameterizedTest + @MethodSource("createAlignments") public void testAlignedAccess(long align) { ValueLayout layout = ValueLayout.JAVA_INT .withOrder(ByteOrder.BIG_ENDIAN); - assertEquals(layout.byteAlignment(), 4); + assertEquals(4, layout.byteAlignment()); ValueLayout aligned = layout.withByteAlignment(align); - assertEquals(aligned.byteAlignment(), align); //unreasonable alignment here, to make sure access throws + assertEquals(align, aligned.byteAlignment()); //unreasonable alignment here, to make sure access throws VarHandle vh = aligned.varHandle(); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(aligned); @@ -69,24 +74,26 @@ public void testAlignedAccess(long align) { vh.set(nextSegment, 0L, 0xffffff); int val = (int)vh.get(segment, 0L); - assertEquals(val, -42); + assertEquals(-42, val); } } - @Test(dataProvider = "alignments") + @ParameterizedTest + @MethodSource("createAlignments") public void testUnalignedPath(long align) { MemoryLayout layout = ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN); MemoryLayout aligned = layout.withByteAlignment(align).withName("value"); try { GroupLayout alignedGroup = MemoryLayout.structLayout(MemoryLayout.paddingLayout(1), aligned); alignedGroup.varHandle(PathElement.groupElement("value")); - assertEquals(align, 1); //this is the only case where path is aligned + assertEquals(1, align); //this is the only case where path is aligned } catch (IllegalArgumentException ex) { - assertNotEquals(align, 1); //if align != 8, path is always unaligned + assertNotEquals(1, align); //if align != 8, path is always unaligned } } - @Test(dataProvider = "alignments") + @ParameterizedTest + @MethodSource("createAlignments") public void testUnalignedSequence(long align) { try { SequenceLayout layout = MemoryLayout.sequenceLayout(5, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withByteAlignment(align)); @@ -111,22 +118,23 @@ public void testPackedAccess() { GroupLayout g = MemoryLayout.structLayout(vChar.withByteAlignment(1).withName("a"), vShort.withByteAlignment(1).withName("b"), vInt.withByteAlignment(1).withName("c")); - assertEquals(g.byteAlignment(), 1); + assertEquals(1, g.byteAlignment()); VarHandle vh_c = g.varHandle(PathElement.groupElement("a")); VarHandle vh_s = g.varHandle(PathElement.groupElement("b")); VarHandle vh_i = g.varHandle(PathElement.groupElement("c")); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(g);; vh_c.set(segment, 0L, Byte.MIN_VALUE); - assertEquals(vh_c.get(segment, 0L), Byte.MIN_VALUE); + assertEquals(Byte.MIN_VALUE, vh_c.get(segment, 0L)); vh_s.set(segment, 0L, Short.MIN_VALUE); - assertEquals(vh_s.get(segment, 0L), Short.MIN_VALUE); + assertEquals(Short.MIN_VALUE, vh_s.get(segment, 0L)); vh_i.set(segment, 0L, Integer.MIN_VALUE); - assertEquals(vh_i.get(segment, 0L), Integer.MIN_VALUE); + assertEquals(Integer.MIN_VALUE, vh_i.get(segment, 0L)); } } - @Test(dataProvider = "alignments") + @ParameterizedTest + @MethodSource("createAlignments") public void testActualByteAlignment(long align) { if (align > (1L << 10)) { return; @@ -135,8 +143,8 @@ public void testActualByteAlignment(long align) { var segment = arena.allocate(4, align); assertTrue(segment.maxByteAlignment() >= align); // Power of two? - assertEquals(Long.bitCount(segment.maxByteAlignment()), 1); - assertEquals(segment.asSlice(1).maxByteAlignment(), 1); + assertEquals(1, Long.bitCount(segment.maxByteAlignment())); + assertEquals(1, segment.asSlice(1).maxByteAlignment()); } } @@ -149,8 +157,8 @@ public void testActualByteAlignmentMappedSegment() throws IOException { // be positive. assertTrue(segment.maxByteAlignment() >= Byte.BYTES); // Power of two? - assertEquals(Long.bitCount(segment.maxByteAlignment()), 1); - assertEquals(segment.asSlice(1).maxByteAlignment(), 1); + assertEquals(1, Long.bitCount(segment.maxByteAlignment())); + assertEquals(1, segment.asSlice(1).maxByteAlignment()); } finally { tmp.delete(); } @@ -159,25 +167,24 @@ public void testActualByteAlignmentMappedSegment() throws IOException { @Test() public void testActualByteAlignmentNull() { long alignment = MemorySegment.NULL.maxByteAlignment(); - assertEquals(1L << 62, alignment); + assertEquals(alignment, 1L << 62); } - @Test(dataProvider = "heapSegments") + @ParameterizedTest + @MethodSource("heapSegments") public void testActualByteAlignmentHeap(MemorySegment segment, int bytes) { - assertEquals(segment.maxByteAlignment(), bytes); + assertEquals(bytes, segment.maxByteAlignment()); // A slice at offset 1 should always have an alignment of 1 var segmentSlice = segment.asSlice(1); - assertEquals(segmentSlice.maxByteAlignment(), 1); + assertEquals(1, segmentSlice.maxByteAlignment()); } - @DataProvider(name = "alignments") public Object[][] createAlignments() { return LongStream.range(1, 20) .mapToObj(v -> new Object[] { 1L << v }) .toArray(Object[][]::new); } - @DataProvider(name = "heapSegments") public Object[][] heapSegments() { return Stream.of( new Object[]{MemorySegment.ofArray(new byte[]{1}), Byte.BYTES}, diff --git a/test/jdk/java/foreign/TestMemoryDereference.java b/test/jdk/java/foreign/TestMemoryDereference.java index 4680b148b655..d8d373ba0399 100644 --- a/test/jdk/java/foreign/TestMemoryDereference.java +++ b/test/jdk/java/foreign/TestMemoryDereference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestMemoryDereference + * @run junit TestMemoryDereference */ import java.lang.foreign.MemorySegment; @@ -32,11 +32,15 @@ import java.nio.ByteOrder; import java.lang.foreign.ValueLayout; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMemoryDereference { static class Accessor { @@ -77,9 +81,9 @@ void test() { MemorySegment segment = MemorySegment.ofArray(new byte[32]); ByteBuffer buffer = segment.asByteBuffer(); segmentSetter.set(segment, value); - assertEquals(bufferGetter.get(buffer), value); + assertEquals(value, bufferGetter.get(buffer)); bufferSetter.set(buffer, value); - assertEquals(value, segmentGetter.get(segment)); + assertEquals(segmentGetter.get(segment), value); } Accessor of(Z value, @@ -89,7 +93,8 @@ Accessor of(Z value, } } - @Test(dataProvider = "accessors") + @ParameterizedTest + @MethodSource("accessors") public void testMemoryAccess(String testName, Accessor accessor) { accessor.test(); } @@ -98,7 +103,6 @@ public void testMemoryAccess(String testName, Accessor accessor) { static final ByteOrder LE = ByteOrder.LITTLE_ENDIAN; static final ByteOrder NE = ByteOrder.nativeOrder(); - @DataProvider(name = "accessors") static Object[][] accessors() { return new Object[][]{ diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java index b06e2707c399..03cd5b4c1298 100644 --- a/test/jdk/java/foreign/TestMemorySession.java +++ b/test/jdk/java/foreign/TestMemorySession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @modules java.base/jdk.internal.foreign - * @run testng/othervm TestMemorySession + * @run junit/othervm TestMemorySession */ import java.lang.foreign.Arena; @@ -36,11 +36,14 @@ import java.util.function.Supplier; import java.util.stream.IntStream; import jdk.internal.foreign.MemorySessionImpl; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMemorySession { final static int N_THREADS = 100; @@ -53,13 +56,14 @@ public void testConfined() { int delta = i; addCloseAction(arena, () -> acc.addAndGet(delta)); } - assertEquals(acc.get(), 0); + assertEquals(0, acc.get()); arena.close(); - assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); + assertEquals(IntStream.range(0, N_THREADS).sum(), acc.get()); } - @Test(dataProvider = "sharedSessions") + @ParameterizedTest + @MethodSource("sharedSessions") public void testSharedSingleThread(ArenaSupplier arenaSupplier) { AtomicInteger acc = new AtomicInteger(); Arena session = arenaSupplier.get(); @@ -67,11 +71,11 @@ public void testSharedSingleThread(ArenaSupplier arenaSupplier) { int delta = i; addCloseAction(session, () -> acc.addAndGet(delta)); } - assertEquals(acc.get(), 0); + assertEquals(0, acc.get()); if (!TestMemorySession.ArenaSupplier.isImplicit(session)) { TestMemorySession.ArenaSupplier.close(session); - assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); + assertEquals(IntStream.range(0, N_THREADS).sum(), acc.get()); } else { session = null; int expected = IntStream.range(0, N_THREADS).sum(); @@ -81,7 +85,8 @@ public void testSharedSingleThread(ArenaSupplier arenaSupplier) { } } - @Test(dataProvider = "sharedSessions") + @ParameterizedTest + @MethodSource("sharedSessions") public void testSharedMultiThread(ArenaSupplier arenaSupplier) { AtomicInteger acc = new AtomicInteger(); List threads = new ArrayList<>(); @@ -101,7 +106,7 @@ public void testSharedMultiThread(ArenaSupplier arenaSupplier) { }); threads.add(thread); } - assertEquals(acc.get(), 0); + assertEquals(0, acc.get()); threads.forEach(Thread::start); // if no cleaner, close - not all segments might have been added to the session! @@ -126,7 +131,7 @@ public void testSharedMultiThread(ArenaSupplier arenaSupplier) { }); if (!TestMemorySession.ArenaSupplier.isImplicit(session)) { - assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); + assertEquals(IntStream.range(0, N_THREADS).sum(), acc.get()); } else { session = null; sessionRef.set(null); @@ -150,7 +155,7 @@ public void testLockSingleThread() { while (true) { try { arena.close(); - assertEquals(handles.size(), 0); + assertEquals(0, handles.size()); break; } catch (IllegalStateException ex) { assertTrue(handles.size() > 0); @@ -180,7 +185,7 @@ public void testLockSharedMultiThread() { while (true) { try { arena.close(); - assertEquals(lockCount.get(), 0); + assertEquals(0, lockCount.get()); break; } catch (IllegalStateException ex) { waitSomeTime(); @@ -215,13 +220,14 @@ public void testCloseConfinedLock() { try { t.join(); assertNotNull(failure.get()); - assertEquals(failure.get().getClass(), WrongThreadException.class); + assertEquals(WrongThreadException.class, failure.get().getClass()); } catch (Throwable ex) { throw new AssertionError(ex); } } - @Test(dataProvider = "allSessions") + @ParameterizedTest + @MethodSource("allSessions") public void testSessionAcquires(ArenaSupplier ArenaSupplier) { Arena session = ArenaSupplier.get(); acquireRecursive(session, 5); @@ -299,7 +305,8 @@ public void testConfinedSessionWithSharedDependency() { root.close(); } - @Test(dataProvider = "nonCloseableSessions") + @ParameterizedTest + @MethodSource("nonCloseableSessions") public void testNonCloseableSessions(ArenaSupplier arenaSupplier) { var arena = arenaSupplier.get(); var sessionImpl = ((MemorySessionImpl) arena.scope()); @@ -308,14 +315,15 @@ public void testNonCloseableSessions(ArenaSupplier arenaSupplier) { sessionImpl.close()); } - @Test(dataProvider = "allSessionsAndGlobal") + @ParameterizedTest + @MethodSource("allSessionsAndGlobal") public void testIsCloseableBy(ArenaSupplier arenaSupplier) { var arena = arenaSupplier.get(); var sessionImpl = ((MemorySessionImpl) arena.scope()); - assertEquals(sessionImpl.isCloseableBy(Thread.currentThread()), sessionImpl.isCloseable()); + assertEquals(sessionImpl.isCloseable(), sessionImpl.isCloseableBy(Thread.currentThread())); Thread otherThread = new Thread(); boolean isCloseableByOther = sessionImpl.isCloseable() && !"ConfinedSession".equals(sessionImpl.getClass().getSimpleName()); - assertEquals(sessionImpl.isCloseableBy(otherThread), isCloseableByOther); + assertEquals(isCloseableByOther, sessionImpl.isCloseableBy(otherThread)); } /** @@ -402,7 +410,6 @@ private void kickGC() { } } - @DataProvider static Object[][] drops() { return new Object[][] { { (Supplier) Arena::ofConfined}, @@ -444,7 +451,6 @@ static ArenaSupplier ofArena(Supplier arenaSupplier) { } } - @DataProvider(name = "sharedSessions") static Object[][] sharedSessions() { return new Object[][] { { ArenaSupplier.ofArena(Arena::ofShared) }, @@ -452,7 +458,6 @@ static Object[][] sharedSessions() { }; } - @DataProvider(name = "allSessions") static Object[][] allSessions() { return new Object[][] { { ArenaSupplier.ofArena(Arena::ofConfined) }, @@ -461,7 +466,6 @@ static Object[][] allSessions() { }; } - @DataProvider(name = "nonCloseableSessions") static Object[][] nonCloseableSessions() { return new Object[][] { { ArenaSupplier.ofGlobal() }, @@ -469,7 +473,6 @@ static Object[][] nonCloseableSessions() { }; } - @DataProvider(name = "allSessionsAndGlobal") static Object[][] allSessionsAndGlobal() { return new Object[][] { { ArenaSupplier.ofArena(Arena::ofConfined) }, diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index fa01f1553ebf..fc8854d74920 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @bug 8323552 - * @run testng/timeout=480 TestMismatch + * @run junit/timeout=480 TestMismatch */ import java.lang.foreign.Arena; @@ -39,12 +39,16 @@ import java.util.function.IntFunction; import java.util.stream.Stream; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestMismatch { // stores an increasing sequence of values into the memory of the given segment @@ -55,56 +59,76 @@ static MemorySegment initializeSegment(MemorySegment segment) { return segment; } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeSrcFromOffset(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, -1, 0, s2, 0, 0); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, -1, 0, s2, 0, 0); + }); } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeDstFromOffset(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, 0, 0, s2, -1, 0); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, 0, 0, s2, -1, 0); + }); } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeSrcToOffset(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, 0, -1, s2, 0, 0); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, 0, -1, s2, 0, 0); + }); } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeDstToOffset(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, 0, 0, s2, 0, -1); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, 0, 0, s2, 0, -1); + }); } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeSrcLength(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, 3, 2, s2, 0, 0); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, 3, 2, s2, 0, 0); + }); } - @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + @ParameterizedTest + @MethodSource("slices") public void testNegativeDstLength(MemorySegment s1, MemorySegment s2) { - MemorySegment.mismatch(s1, 0, 0, s2, 3, 2); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.mismatch(s1, 0, 0, s2, 3, 2); + }); } - @Test(dataProvider = "slices") + @ParameterizedTest + @MethodSource("slices") public void testSameValues(MemorySegment ss1, MemorySegment ss2) { out.format("testSameValues s1:%s, s2:%s\n", ss1, ss2); MemorySegment s1 = initializeSegment(ss1); MemorySegment s2 = initializeSegment(ss2); if (s1.byteSize() == s2.byteSize()) { - assertEquals(s1.mismatch(s2), -1); // identical - assertEquals(s2.mismatch(s1), -1); + assertEquals(-1, s1.mismatch(s2)); // identical + assertEquals(-1, s2.mismatch(s1)); } else if (s1.byteSize() > s2.byteSize()) { - assertEquals(s1.mismatch(s2), s2.byteSize()); // proper prefix - assertEquals(s2.mismatch(s1), s2.byteSize()); + assertEquals(s2.byteSize(), s1.mismatch(s2)); // proper prefix + assertEquals(s2.byteSize(), s2.mismatch(s1)); } else { assert s1.byteSize() < s2.byteSize(); - assertEquals(s1.mismatch(s2), s1.byteSize()); // proper prefix - assertEquals(s2.mismatch(s1), s1.byteSize()); + assertEquals(s1.byteSize(), s1.mismatch(s2)); // proper prefix + assertEquals(s1.byteSize(), s2.mismatch(s1)); } } - @Test(dataProvider = "slicesStatic") + @ParameterizedTest + @MethodSource("slicesStatic") public void testSameValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { out.format("testSameValuesStatic s1:%s, s2:%s\n", ss1, ss2); MemorySegment s1 = initializeSegment(ss1.toSlice()); @@ -114,13 +138,13 @@ public void testSameValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) long bytes = i - ss2.offset; long expected = (bytes == ss1.size) ? -1 : Long.min(ss1.size, bytes); - assertEquals(MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, i), expected); + assertEquals(expected, MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, i)); } for (long i = ss1.offset ; i < ss1.size ; i++) { long bytes = i - ss1.offset; long expected = (bytes == ss2.size) ? -1 : Long.min(ss2.size, bytes); - assertEquals(MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, i), expected); + assertEquals(expected, MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, i)); } } @@ -160,21 +184,21 @@ public void random() { } // They are not equal and differs in position beginDiff - assertEquals(src.mismatch(dst), beginDiff); - assertEquals(dst.mismatch(src), beginDiff); + assertEquals(beginDiff, src.mismatch(dst)); + assertEquals(beginDiff, dst.mismatch(src)); } else { // In this branch, there is no injection if (src.byteSize() == dst.byteSize()) { // The content matches and they are of equal size - assertEquals(src.mismatch(dst), -1); - assertEquals(dst.mismatch(src), -1); + assertEquals(-1, src.mismatch(dst)); + assertEquals(-1, dst.mismatch(src)); } else { // The content matches but they are of different length // Remember, the size of src is always smaller or equal // to the size of dst. - assertEquals(src.mismatch(dst), src.byteSize()); - assertEquals(dst.mismatch(src), src.byteSize()); + assertEquals(src.byteSize(), src.mismatch(dst)); + assertEquals(src.byteSize(), dst.mismatch(src)); } } } @@ -186,7 +210,8 @@ static byte randomByte(Random rnd) { return (byte) rnd.nextInt(Byte.MIN_VALUE, Byte.MAX_VALUE + 1); } - @Test(dataProvider = "slices") + @ParameterizedTest + @MethodSource("slices") public void testDifferentValues(MemorySegment s1, MemorySegment s2) { out.format("testDifferentValues s1:%s, s2:%s\n", s1, s2); s1 = initializeSegment(s1); @@ -197,21 +222,22 @@ public void testDifferentValues(MemorySegment s1, MemorySegment s2) { s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); if (s1.byteSize() == s2.byteSize()) { - assertEquals(s1.mismatch(s2), expectedMismatchOffset); - assertEquals(s2.mismatch(s1), expectedMismatchOffset); + assertEquals(expectedMismatchOffset, s1.mismatch(s2)); + assertEquals(expectedMismatchOffset, s2.mismatch(s1)); } else if (s1.byteSize() > s2.byteSize()) { - assertEquals(s1.mismatch(s2), expectedMismatchOffset); - assertEquals(s2.mismatch(s1), expectedMismatchOffset); + assertEquals(expectedMismatchOffset, s1.mismatch(s2)); + assertEquals(expectedMismatchOffset, s2.mismatch(s1)); } else { assert s1.byteSize() < s2.byteSize(); var off = Math.min(s1.byteSize(), expectedMismatchOffset); - assertEquals(s1.mismatch(s2), off); // proper prefix - assertEquals(s2.mismatch(s1), off); + assertEquals(off, s1.mismatch(s2)); // proper prefix + assertEquals(off, s2.mismatch(s1)); } } } - @Test(dataProvider = "slicesStatic") + @ParameterizedTest + @MethodSource("slicesStatic") public void testDifferentValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { out.format("testDifferentValues s1:%s, s2:%s\n", ss1, ss2); @@ -223,10 +249,10 @@ public void testDifferentValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2.toSlice().set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); for (long j = expectedMismatchOffset + 1 ; j < ss2.size ; j++) { - assertEquals(MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, j + ss2.offset), expectedMismatchOffset); + assertEquals(expectedMismatchOffset, MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, j + ss2.offset)); } for (long j = expectedMismatchOffset + 1 ; j < ss1.size ; j++) { - assertEquals(MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, j + ss1.offset), expectedMismatchOffset); + assertEquals(expectedMismatchOffset, MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, j + ss1.offset)); } } } @@ -234,12 +260,12 @@ public void testDifferentValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize @Test public void testEmpty() { var s1 = MemorySegment.ofArray(new byte[0]); - assertEquals(s1.mismatch(s1), -1); + assertEquals(-1, s1.mismatch(s1)); try (Arena arena = Arena.ofConfined()) { var nativeSegment = arena.allocate(4, 4);; var s2 = nativeSegment.asSlice(0, 0); - assertEquals(s1.mismatch(s2), -1); - assertEquals(s2.mismatch(s1), -1); + assertEquals(-1, s1.mismatch(s2)); + assertEquals(-1, s2.mismatch(s1)); } } @@ -250,9 +276,9 @@ public void testLarge() { try (Arena arena = Arena.ofConfined()) { var s1 = arena.allocate((long) Integer.MAX_VALUE + 10L, 8);; var s2 = arena.allocate((long) Integer.MAX_VALUE + 10L, 8);; - assertEquals(s1.mismatch(s1), -1); - assertEquals(s1.mismatch(s2), -1); - assertEquals(s2.mismatch(s1), -1); + assertEquals(-1, s1.mismatch(s1)); + assertEquals(-1, s1.mismatch(s2)); + assertEquals(-1, s2.mismatch(s1)); testLargeAcrossMaxBoundary(s1, s2); @@ -266,13 +292,13 @@ private void testLargeAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { var s3 = s1.asSlice(0, i); var s4 = s2.asSlice(0, i); // instance - assertEquals(s3.mismatch(s3), -1); - assertEquals(s3.mismatch(s4), -1); - assertEquals(s4.mismatch(s3), -1); + assertEquals(-1, s3.mismatch(s3)); + assertEquals(-1, s3.mismatch(s4)); + assertEquals(-1, s4.mismatch(s3)); // static - assertEquals(MemorySegment.mismatch(s1, 0, s1.byteSize(), s1, 0, i), -1); - assertEquals(MemorySegment.mismatch(s2, 0, s1.byteSize(), s1, 0, i), -1); - assertEquals(MemorySegment.mismatch(s1, 0, s1.byteSize(), s2, 0, i), -1); + assertEquals(-1, MemorySegment.mismatch(s1, 0, s1.byteSize(), s1, 0, i)); + assertEquals(-1, MemorySegment.mismatch(s2, 0, s1.byteSize(), s1, 0, i)); + assertEquals(-1, MemorySegment.mismatch(s1, 0, s1.byteSize(), s2, 0, i)); } } @@ -280,8 +306,8 @@ private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); long expectedMismatchOffset = i; - assertEquals(s1.mismatch(s2), expectedMismatchOffset); - assertEquals(s2.mismatch(s1), expectedMismatchOffset); + assertEquals(expectedMismatchOffset, s1.mismatch(s2)); + assertEquals(expectedMismatchOffset, s2.mismatch(s1)); } } @@ -351,22 +377,22 @@ public void testSameSegment() { long match = MemorySegment.mismatch( segment, 0L, 4L, segment, 4L, 8L); - assertEquals(match, -1); + assertEquals(-1, match); long noMatch = MemorySegment.mismatch( segment, 0L, 4L, segment, 1L, 5L); - assertEquals(noMatch, 0); + assertEquals(0, noMatch); long noMatchEnd = MemorySegment.mismatch( segment, 0L, 2L, segment, 8L, 10L); - assertEquals(noMatchEnd, 1); + assertEquals(1, noMatchEnd); long same = MemorySegment.mismatch( segment, 0L, 8L, segment, 0L, 8L); - assertEquals(same, -1); + assertEquals(-1, same); } enum SegmentKind { @@ -393,7 +419,6 @@ long endOffset() { } }; - @DataProvider(name = "slicesStatic") static Object[][] slicesStatic() { int[] sizes = { 16, 8, 1 }; List aSliceOffsetAndSizes = new ArrayList<>(); @@ -419,7 +444,6 @@ static Object[][] slicesStatic() { return sliceArray; } - @DataProvider(name = "slices") static Object[][] slices() { Object[][] slicesStatic = slicesStatic(); return Stream.of(slicesStatic) diff --git a/test/jdk/java/foreign/TestNULLAddress.java b/test/jdk/java/foreign/TestNULLAddress.java index 32d19fb48740..a395f40117fa 100644 --- a/test/jdk/java/foreign/TestNULLAddress.java +++ b/test/jdk/java/foreign/TestNULLAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,11 @@ /* * @test - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * TestNULLAddress */ -import org.testng.annotations.Test; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; @@ -37,7 +36,8 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestNULLAddress { @@ -47,18 +47,22 @@ public class TestNULLAddress { static final Linker LINKER = Linker.nativeLinker(); - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNULLLinking() { - LINKER.downcallHandle( - MemorySegment.NULL, - FunctionDescriptor.ofVoid()); + assertThrows(IllegalArgumentException.class, () -> { + LINKER.downcallHandle( + MemorySegment.NULL, + FunctionDescriptor.ofVoid()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNULLVirtual() throws Throwable { MethodHandle mh = LINKER.downcallHandle( FunctionDescriptor.ofVoid()); - mh.invokeExact(MemorySegment.NULL); + assertThrows(IllegalArgumentException.class, () -> { + mh.invokeExact(MemorySegment.NULL); + }); } @Test diff --git a/test/jdk/java/foreign/TestNative.java b/test/jdk/java/foreign/TestNative.java index c39a1292b400..a6fb348f65fe 100644 --- a/test/jdk/java/foreign/TestNative.java +++ b/test/jdk/java/foreign/TestNative.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,12 @@ /* * @test - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestNative + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestNative */ import java.lang.foreign.*; import java.lang.foreign.MemoryLayout.PathElement; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.VarHandle; import java.nio.Buffer; @@ -49,8 +47,14 @@ import java.util.function.Function; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestNative extends NativeTestHelper { static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, @@ -108,13 +112,13 @@ static void checkBytes(MemorySegment base, SequenceLayout lay Object bufferValue = nativeBufferExtractor.apply(z, (int)i); Object rawValue = nativeRawExtractor.apply(base.address(), (int)i); if (handleValue instanceof Number) { - assertEquals(((Number)handleValue).longValue(), i); - assertEquals(((Number)bufferValue).longValue(), i); - assertEquals(((Number)rawValue).longValue(), i); + assertEquals(i, ((Number)handleValue).longValue()); + assertEquals(i, ((Number)bufferValue).longValue()); + assertEquals(i, ((Number)rawValue).longValue()); } else { - assertEquals((long)(char)handleValue, i); - assertEquals((long)(char)bufferValue, i); - assertEquals((long)(char)rawValue, i); + assertEquals(i, (long)(char)handleValue); + assertEquals(i, (long)(char)bufferValue); + assertEquals(i, (long)(char)rawValue); } } } @@ -137,7 +141,8 @@ static void checkBytes(MemorySegment base, SequenceLayout lay public static native long getCapacity(Buffer buffer); - @Test(dataProvider="nativeAccessOps") + @ParameterizedTest + @MethodSource("nativeAccessOps") public void testNativeAccess(Consumer checker, Consumer initializer, SequenceLayout seq) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(seq);; @@ -146,7 +151,8 @@ public void testNativeAccess(Consumer checker, Consumer bufferFunction, int elemSize) { int capacity = (int)doubles.byteSize(); try (Arena arena = Arena.ofConfined()) { @@ -154,8 +160,8 @@ public void testNativeCapacity(Function bufferFunction, int ByteBuffer bb = segment.asByteBuffer(); Buffer buf = bufferFunction.apply(bb); int expected = capacity / elemSize; - assertEquals(buf.capacity(), expected); - assertEquals(getCapacity(buf), expected); + assertEquals(expected, buf.capacity()); + assertEquals(expected, getCapacity(buf)); } } @@ -176,7 +182,7 @@ public void testMallocSegment() { try (Arena arena = Arena.ofConfined()) { mallocSegment = addr.asSlice(0, 12) .reinterpret(arena, TestNative::freeMemory); - assertEquals(mallocSegment.byteSize(), 12); + assertEquals(12, mallocSegment.byteSize()); //free here } assertTrue(!mallocSegment.scope().isAlive()); @@ -186,7 +192,7 @@ public void testMallocSegment() { public void testAddressAccess() { MemorySegment addr = allocateMemory(4); addr.set(JAVA_INT, 0, 42); - assertEquals(addr.get(JAVA_INT, 0), 42); + assertEquals(42, addr.get(JAVA_INT, 0)); freeMemory(addr); } @@ -203,7 +209,6 @@ public void testBadResize() { System.loadLibrary("NativeAccess"); } - @DataProvider(name = "nativeAccessOps") public Object[][] nativeAccessOps() { Consumer byteInitializer = (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, 0L, pos, (byte)(long)pos)); @@ -246,7 +251,6 @@ public Object[][] nativeAccessOps() { }; } - @DataProvider(name = "buffers") public Object[][] buffers() { return new Object[][] { { (Function)bb -> bb, 1 }, diff --git a/test/jdk/java/foreign/TestNulls.java b/test/jdk/java/foreign/TestNulls.java index 6822863c2ca1..8825809930af 100644 --- a/test/jdk/java/foreign/TestNulls.java +++ b/test/jdk/java/foreign/TestNulls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @modules java.base/jdk.internal.ref - * @run testng/othervm + * @run junit/othervm * --enable-native-access=ALL-UNNAMED * TestNulls */ @@ -32,9 +32,6 @@ import java.lang.foreign.*; import jdk.internal.ref.CleanerFactory; -import org.testng.annotations.DataProvider; -import org.testng.annotations.NoInjection; -import org.testng.annotations.Test; import java.lang.constant.Constable; import java.lang.foreign.Arena; @@ -62,8 +59,12 @@ import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_LONG; -import static org.testng.Assert.*; -import static org.testng.Assert.fail; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * This test makes sure that public API classes (listed in {@link TestNulls#CLASSES}) throws NPEs whenever @@ -75,6 +76,7 @@ * by adding/removing default mappings for standard carrier types (see {@link #DEFAULT_VALUES} or by * adding/removing custom replacements (see {@link #REPLACEMENT_VALUES}). */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestNulls { static final Class[] CLASSES = new Class[] { @@ -189,20 +191,20 @@ static void addReplacements(Class carrier, Z... value) { addReplacements(Set.class, null, Stream.of(new Object[] { null }).collect(Collectors.toSet())); } - @Test(dataProvider = "cases") - public void testNulls(String testName, @NoInjection Method meth, Object receiver, Object[] args) { + @ParameterizedTest(autoCloseArguments = false) + @MethodSource("cases") + public void testNulls(String testName, Method meth, Object receiver, Object[] args) { try { meth.invoke(receiver, args); fail("Method invocation completed normally"); } catch (InvocationTargetException ex) { Class cause = ex.getCause().getClass(); - assertEquals(cause, NullPointerException.class, "got " + cause.getName() + " - expected NullPointerException"); + assertEquals(NullPointerException.class, cause, "got " + cause.getName() + " - expected NullPointerException"); } catch (Throwable ex) { fail("Unexpected exception: " + ex); } } - @DataProvider(name = "cases") static Iterator cases() { List cases = new ArrayList<>(); for (Class clazz : CLASSES) { diff --git a/test/jdk/java/foreign/TestOfBufferIssue.java b/test/jdk/java/foreign/TestOfBufferIssue.java index c30384efc692..e257d6586531 100644 --- a/test/jdk/java/foreign/TestOfBufferIssue.java +++ b/test/jdk/java/foreign/TestOfBufferIssue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,18 +22,18 @@ * */ -import org.testng.annotations.*; import java.lang.foreign.MemorySegment; import java.nio.CharBuffer; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; /* * @test * @bug 8294621 * @summary test that StringCharBuffer is not accepted by MemorySegment::ofBuffer - * @run testng TestOfBufferIssue + * @run junit TestOfBufferIssue */ public class TestOfBufferIssue { diff --git a/test/jdk/java/foreign/TestReshape.java b/test/jdk/java/foreign/TestReshape.java index 5b64a3d38b67..2eedfd936abf 100644 --- a/test/jdk/java/foreign/TestReshape.java +++ b/test/jdk/java/foreign/TestReshape.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestReshape + * @run junit TestReshape */ import java.lang.foreign.MemoryLayout; @@ -34,12 +34,17 @@ import java.util.List; import java.util.stream.LongStream; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestReshape { - @Test(dataProvider = "shapes") + @ParameterizedTest + @MethodSource("shapes") public void testReshape(MemoryLayout layout, long[] expectedShape) { long flattenedSize = LongStream.of(expectedShape).reduce(1L, Math::multiplyExact); SequenceLayout seq_flattened = MemoryLayout.sequenceLayout(flattenedSize, layout); @@ -47,32 +52,40 @@ public void testReshape(MemoryLayout layout, long[] expectedShape) { for (long[] shape : new Shape(expectedShape)) { SequenceLayout seq_shaped = seq_flattened.reshape(shape); assertDimensions(seq_shaped, expectedShape); - assertEquals(seq_shaped.flatten(), seq_flattened); + assertEquals(seq_flattened, seq_shaped.flatten()); } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testInvalidReshape() { SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); - seq.reshape(3, 2); + assertThrows(IllegalArgumentException.class, () -> { + seq.reshape(3, 2); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadReshapeInference() { SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); - seq.reshape(-1, -1); + assertThrows(IllegalArgumentException.class, () -> { + seq.reshape(-1, -1); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadReshapeParameterZero() { SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); - seq.reshape(0, 4); + assertThrows(IllegalArgumentException.class, () -> { + seq.reshape(0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadReshapeParameterNegative() { SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); - seq.reshape(-2, 2); + assertThrows(IllegalArgumentException.class, () -> { + seq.reshape(-2, 2); + }); } static void assertDimensions(SequenceLayout layout, long... dims) { @@ -81,7 +94,7 @@ static void assertDimensions(SequenceLayout layout, long... dims) { if (prev != null) { layout = (SequenceLayout)prev.elementLayout(); } - assertEquals(layout.elementCount(), dims[i]); + assertEquals(dims[i], layout.elementCount()); prev = layout; } } @@ -110,7 +123,6 @@ public Iterator iterator() { ValueLayout.JAVA_INT ); - @DataProvider(name = "shapes") Object[][] shapes() { return new Object[][] { { ValueLayout.JAVA_BYTE, new long[] { 256 } }, diff --git a/test/jdk/java/foreign/TestRestricted.java b/test/jdk/java/foreign/TestRestricted.java index 771037ff8ba9..fc3012df7185 100644 --- a/test/jdk/java/foreign/TestRestricted.java +++ b/test/jdk/java/foreign/TestRestricted.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,11 @@ * @test * @modules java.base/jdk.internal.javac * @modules java.base/jdk.internal.reflect - * @run testng TestRestricted + * @run junit TestRestricted */ import jdk.internal.javac.Restricted; import jdk.internal.reflect.CallerSensitive; -import org.testng.annotations.Test; import java.io.IOException; import java.io.UncheckedIOException; @@ -57,8 +56,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; /** * This test checks all methods in java.base to make sure that methods annotated with {@link Restricted} are diff --git a/test/jdk/java/foreign/TestScope.java b/test/jdk/java/foreign/TestScope.java index cfc1f3deaff3..67458aad0d57 100644 --- a/test/jdk/java/foreign/TestScope.java +++ b/test/jdk/java/foreign/TestScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * 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,9 @@ /* * @test - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestScope + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestScope */ -import org.testng.annotations.*; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -37,7 +36,8 @@ import java.util.HexFormat; import java.util.stream.LongStream; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestScope { @@ -49,21 +49,21 @@ public class TestScope { public void testDifferentArrayScope() { MemorySegment.Scope scope1 = MemorySegment.ofArray(new byte[10]).scope(); MemorySegment.Scope scope2 = MemorySegment.ofArray(new byte[10]).scope(); - assertNotEquals(scope1, scope2); + assertNotEquals(scope2, scope1); } @Test public void testDifferentBufferScope() { MemorySegment.Scope scope1 = MemorySegment.ofBuffer(ByteBuffer.allocateDirect(10)).scope(); MemorySegment.Scope scope2 = MemorySegment.ofBuffer(ByteBuffer.allocateDirect(10)).scope(); - assertNotEquals(scope1, scope2); + assertNotEquals(scope2, scope1); } @Test public void testDifferentArenaScope() { MemorySegment.Scope scope1 = Arena.ofAuto().allocate(10).scope(); MemorySegment.Scope scope2 = Arena.ofAuto().allocate(10).scope(); - assertNotEquals(scope1, scope2); + assertNotEquals(scope2, scope1); } @Test @@ -71,7 +71,7 @@ public void testSameArrayScope() { byte[] arr = new byte[10]; assertEquals(MemorySegment.ofArray(arr).scope(), MemorySegment.ofArray(arr).scope()); ByteBuffer buf = ByteBuffer.wrap(arr); - assertEquals(MemorySegment.ofArray(arr).scope(), MemorySegment.ofBuffer(buf).scope()); + assertEquals(MemorySegment.ofBuffer(buf).scope(), MemorySegment.ofArray(arr).scope()); testDerivedBufferScope(MemorySegment.ofArray(arr)); } @@ -87,7 +87,7 @@ public void testSameArenaScope() { try (Arena arena = Arena.ofConfined()) { MemorySegment segment1 = arena.allocate(10); MemorySegment segment2 = arena.allocate(10); - assertEquals(segment1.scope(), segment2.scope()); + assertEquals(segment2.scope(), segment1.scope()); testDerivedBufferScope(segment1); } } @@ -96,9 +96,9 @@ public void testSameArenaScope() { public void testSameNativeScope() { MemorySegment segment1 = MemorySegment.ofAddress(42); MemorySegment segment2 = MemorySegment.ofAddress(43); - assertEquals(segment1.scope(), segment2.scope()); - assertEquals(segment1.scope(), segment2.reinterpret(10).scope()); - assertEquals(segment1.scope(), Arena.global().scope()); + assertEquals(segment2.scope(), segment1.scope()); + assertEquals(segment2.reinterpret(10).scope(), segment1.scope()); + assertEquals(Arena.global().scope(), segment1.scope()); testDerivedBufferScope(segment1.reinterpret(10)); } @@ -107,7 +107,7 @@ public void testSameLookupScope() { SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); MemorySegment segment1 = loaderLookup.find("f").get(); MemorySegment segment2 = loaderLookup.find("c").get(); - assertEquals(segment1.scope(), segment2.scope()); + assertEquals(segment2.scope(), segment1.scope()); testDerivedBufferScope(segment1.reinterpret(10)); } @@ -138,7 +138,7 @@ public void testZeroedOfShared() { void testDerivedBufferScope(MemorySegment segment) { ByteBuffer buffer = segment.asByteBuffer(); MemorySegment.Scope expectedScope = segment.scope(); - assertEquals(MemorySegment.ofBuffer(buffer).scope(), expectedScope); + assertEquals(expectedScope, MemorySegment.ofBuffer(buffer).scope()); // buffer slices should have same scope ByteBuffer slice = buffer.slice(0, 2); assertEquals(expectedScope, MemorySegment.ofBuffer(slice).scope()); @@ -153,7 +153,7 @@ void testZeroed(Arena arena) { long byteSize = ZEROED_MEMORY.byteSize(); var segment = arena.allocate(byteSize, Long.BYTES); long mismatch = ZEROED_MEMORY.mismatch(segment); - assertEquals(mismatch, -1); + assertEquals(-1, mismatch); } } diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index 92b4ea5370fe..7cabbf75ee8c 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations */ import java.lang.foreign.Arena; @@ -31,8 +31,6 @@ import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.File; import java.io.IOException; @@ -46,11 +44,16 @@ import java.util.function.Function; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestScopedOperations { static Path tempPath; @@ -65,7 +68,8 @@ public class TestScopedOperations { } } - @Test(dataProvider = "scopedOperations") + @ParameterizedTest + @MethodSource("scopedOperations") public void testOpAfterClose(String name, ScopedOperation scopedOperation) { Arena arena = Arena.ofConfined(); Z obj = scopedOperation.apply(arena); @@ -78,7 +82,8 @@ public void testOpAfterClose(String name, ScopedOperation scopedOperation } } - @Test(dataProvider = "scopedOperations") + @ParameterizedTest + @MethodSource("scopedOperations") public void testOpOutsideConfinement(String name, ScopedOperation scopedOperation) { try (Arena arena = Arena.ofConfined()) { Z obj = scopedOperation.apply(arena); @@ -93,7 +98,7 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO t.start(); t.join(); assertNotNull(failed.get()); - assertEquals(failed.get().getClass(), WrongThreadException.class); + assertEquals(WrongThreadException.class, failed.get().getClass()); assertTrue(failed.get().getMessage().contains("outside")); } catch (InterruptedException ex) { throw new AssertionError(ex); @@ -140,7 +145,6 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, source, JAVA_BYTE, 0, 1), "Arena::allocateFrom/5arg"); }; - @DataProvider(name = "scopedOperations") static Object[][] scopedOperations() { return scopedOperations.stream().map(op -> new Object[] { op.name, op }).toArray(Object[][]::new); } diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index c178f64450dd..63ecfce4d861 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,11 @@ /* * @test * @modules java.base/jdk.internal.foreign - * @run testng/othervm TestSegmentAllocators + * @run junit/othervm TestSegmentAllocators */ import java.lang.foreign.*; -import org.testng.annotations.*; import java.lang.foreign.Arena; import java.lang.invoke.VarHandle; @@ -50,14 +49,20 @@ import java.util.function.BiFunction; import java.util.function.Function; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSegmentAllocators { final static int ELEMS = 128; - @Test(dataProvider = "scalarAllocations") @SuppressWarnings("unchecked") + @ParameterizedTest + @MethodSource("scalarAllocations") public void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction allocationFunction, Function handleFactory) { layout = (L)layout.withByteAlignment(layout.byteSize()); L[] layouts = (L[])new ValueLayout[] { @@ -78,10 +83,10 @@ public void testAllocation(Z value, AllocationFactory SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, arena); for (int i = 0; i < elems; i++) { MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value); - assertEquals(address.byteSize(), alignedLayout.byteSize()); + assertEquals(alignedLayout.byteSize(), address.byteSize()); addressList.add(address); VarHandle handle = handleFactory.apply(alignedLayout); - assertEquals(value, handle.get(address, 0L)); + assertEquals(handle.get(address, 0L), value); } boolean isBound = allocationFactory.isBound(); try { @@ -102,14 +107,18 @@ public void testAllocation(Z value, AllocationFactory static final int SIZE_256M = 1024 * 1024 * 256; - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testReadOnlySlicingAllocator() { - SegmentAllocator.slicingAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + assertThrows(IllegalArgumentException.class, () -> { + SegmentAllocator.slicingAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testReadOnlyPrefixAllocator() { - SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + assertThrows(IllegalArgumentException.class, () -> { + SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + }); } @Test @@ -119,9 +128,9 @@ public void testBigAllocationInUnboundedSession() { SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1)); MemorySegment address = allocator.allocate(i, i); //check size - assertEquals(address.byteSize(), i); + assertEquals(i, address.byteSize()); //check alignment - assertEquals(address.address() % i, 0); + assertEquals(0, address.address() % i); } } } @@ -135,59 +144,83 @@ public void testTooBigForBoundedArena() { } } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationSize(SegmentAllocator allocator) { - allocator.allocate(-1); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(-1); + }); } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationAlignZero(SegmentAllocator allocator) { - allocator.allocate(1, 0); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(1, 0); + }); } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationAlignNeg(SegmentAllocator allocator) { - allocator.allocate(1, -1); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(1, -1); + }); } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationAlignNotPowerTwo(SegmentAllocator allocator) { - allocator.allocate(1, 3); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(1, 3); + }); } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationArrayNegSize(SegmentAllocator allocator) { - allocator.allocate(ValueLayout.JAVA_BYTE, -1); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(ValueLayout.JAVA_BYTE, -1); + }); } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("allocators") public void testBadAllocationArrayOverflow(SegmentAllocator allocator) { - allocator.allocate(ValueLayout.JAVA_LONG, Long.MAX_VALUE); + assertThrows(IllegalArgumentException.class, () -> { + allocator.allocate(ValueLayout.JAVA_LONG, Long.MAX_VALUE); + }); } - @Test(expectedExceptions = OutOfMemoryError.class) + @Test public void testBadArenaNullReturn() { try (Arena arena = Arena.ofConfined()) { - arena.allocate(Long.MAX_VALUE, 2); + assertThrows(OutOfMemoryError.class, () -> { + arena.allocate(Long.MAX_VALUE, 2); + }); } } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void testArenaAllocateFromHeapSegment() { try (Arena arena = Arena.ofConfined()) { var heapSegment = MemorySegment.ofArray(new int[]{1}); - arena.allocateFrom(ValueLayout.ADDRESS, heapSegment); + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + arena.allocateFrom(ValueLayout.ADDRESS, heapSegment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void testAllocatorAllocateFromHeapSegment() { try (Arena arena = Arena.ofConfined()) { SegmentAllocator allocator = SegmentAllocator.prefixAllocator(arena.allocate(16)); var heapSegment = MemorySegment.ofArray(new int[]{1}); - allocator.allocateFrom(ValueLayout.ADDRESS, heapSegment); + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + allocator.allocateFrom(ValueLayout.ADDRESS, heapSegment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } } @@ -288,7 +321,7 @@ public MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment sourc allocator.allocateFrom(ValueLayout.JAVA_FLOAT); allocator.allocateFrom(ValueLayout.JAVA_LONG); allocator.allocateFrom(ValueLayout.JAVA_DOUBLE); - assertEquals(calls.get(), 7); + assertEquals(7, calls.get()); } @Test @@ -307,11 +340,12 @@ public MemorySegment allocate(long size) { }; }; allocator.allocateFrom("Hello"); - assertEquals(calls.get(), 1); + assertEquals(1, calls.get()); } - @Test(dataProvider = "arrayAllocations") + @ParameterizedTest + @MethodSource("arrayAllocations") public void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); Arena[] arenas = { @@ -323,12 +357,35 @@ public void testArray(AllocationFactory allocationFactory, ValueLayout layou SegmentAllocator allocator = allocationFactory.allocator(100, arena); MemorySegment address = allocationFunction.allocate(allocator, layout, arr); Z found = arrayHelper.toArray(address, layout); - assertEquals(found, arr); + assertArraysEqual(arr, found); } } } - @Test(dataProvider = "arrayAllocations") + private static void assertArraysEqual(Object arr, Object found) { + //in JUnit, assertEquals will really only call .equals, and that does not work well for arrays + //there's a set of explicit assertArrayEquals method, but we need "sharp" types for that to work(??): + if (arr instanceof byte[]) { + assertArrayEquals((byte[]) arr, (byte[]) found); + } else if (arr instanceof char[]) { + assertArrayEquals((char[]) arr, (char[]) found); + } else if (arr instanceof short[]) { + assertArrayEquals((short[]) arr, (short[]) found); + } else if (arr instanceof int[]) { + assertArrayEquals((int[]) arr, (int[]) found); + } else if (arr instanceof long[]) { + assertArrayEquals((long[]) arr, (long[]) found); + } else if (arr instanceof float[]) { + assertArrayEquals((float[]) arr, (float[]) found); + } else if (arr instanceof double[]) { + assertArrayEquals((double[]) arr, (double[]) found); + } else { + assertArrayEquals((Object[]) arr, (Object[]) found); + } + } + + @ParameterizedTest + @MethodSource("arrayAllocations") public void testPredicatesAndCommands(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); Arena[] arenas = { @@ -349,7 +406,6 @@ public void testPredicatesAndCommands(AllocationFactory allocationFactory, V } } - @DataProvider(name = "scalarAllocations") static Object[][] scalarAllocations() { List scalarAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { @@ -405,7 +461,6 @@ static Object[][] scalarAllocations() { return scalarAllocations.toArray(Object[][]::new); } - @DataProvider(name = "arrayAllocations") static Object[][] arrayAllocations() { List arrayAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { @@ -609,7 +664,6 @@ public double[] toArray(MemorySegment segment, ValueLayout layout) { }; } - @DataProvider(name = "allocators") static Object[][] allocators() { return new Object[][] { { SegmentAllocator.prefixAllocator(Arena.global().allocate(10, 1)) }, diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index 9a4500b2f5a1..53e0d0d10dfd 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test - * @run testng TestSegmentCopy + * @run junit TestSegmentCopy */ import java.lang.foreign.Arena; @@ -37,18 +37,23 @@ import java.util.List; import java.util.function.IntFunction; -import org.testng.SkipException; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSegmentCopy { static final int TEST_BYTE_SIZE = 16; - @Test(dataProvider = "segmentKinds") + @ParameterizedTest + @MethodSource("segmentKinds") public void testByteCopy(SegmentKind kind1, SegmentKind kind2) { MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE); MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE); @@ -75,7 +80,8 @@ public void testByteCopy(SegmentKind kind1, SegmentKind kind2) { } } - @Test(dataProvider = "conjunctSegments") + @ParameterizedTest + @MethodSource("conjunctSegments") public void testCopy5ArgInvariants(MemorySegment src, MemorySegment dst) { assertThrows(IndexOutOfBoundsException.class, () -> MemorySegment.copy(src, 0, dst, 0, -1)); assertThrows(IndexOutOfBoundsException.class, () -> MemorySegment.copy(src, -1, dst, 0, src.byteSize())); @@ -84,22 +90,26 @@ public void testCopy5ArgInvariants(MemorySegment src, MemorySegment dst) { assertThrows(IndexOutOfBoundsException.class, () -> MemorySegment.copy(src, 0, dst, 1, src.byteSize())); } - @Test(dataProvider = "conjunctSegments") + @ParameterizedTest + @MethodSource("conjunctSegments") public void testConjunctCopy7ArgRight(MemorySegment src, MemorySegment dst) { testConjunctCopy(src, 0, dst, 1, CopyOp.of7Arg()); } - @Test(dataProvider = "conjunctSegments") + @ParameterizedTest + @MethodSource("conjunctSegments") public void testConjunctCopy5ArgRight(MemorySegment src, MemorySegment dst) { testConjunctCopy(src, 0, dst, 1, CopyOp.of5Arg()); } - @Test(dataProvider = "conjunctSegments") + @ParameterizedTest + @MethodSource("conjunctSegments") public void testConjunctCopy7ArgLeft(MemorySegment src, MemorySegment dst) { testConjunctCopy(src, 1, dst, 0, CopyOp.of7Arg()); } - @Test(dataProvider = "conjunctSegments") + @ParameterizedTest + @MethodSource("conjunctSegments") public void testConjunctCopy5ArgLeft(MemorySegment src, MemorySegment dst) { testConjunctCopy(src, 1, dst, 0, CopyOp.of5Arg()); } @@ -121,7 +131,7 @@ void testConjunctCopy(MemorySegment src, long srcOffset, MemorySegment dst, long op.copy(src, srcOffset, dst, dstOffset, 3); byte[] actual = dst.toArray(JAVA_BYTE); - assertEquals(actual, expected); + assertArrayEquals(expected, actual); } } @@ -140,7 +150,8 @@ static CopyOp of7Arg() { } - @Test(dataProvider = "segmentKinds") + @ParameterizedTest + @MethodSource("segmentKinds") public void testByteCopySizes(SegmentKind kind1, SegmentKind kind2) { record Offsets(int src, int dst){} @@ -157,40 +168,46 @@ record Offsets(int src, int dst){} MemorySegment.copy(src, offsets.src(), dst, offsets.dst(), size); //check that copy actually worked for (int i = 0; i < size; i++) { - assertEquals(dst.get(JAVA_BYTE, i + offsets.dst()), (byte) i); + assertEquals((byte) i, dst.get(JAVA_BYTE, i + offsets.dst())); } } } } - @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "segmentKinds") + @ParameterizedTest + @MethodSource("segmentKinds") public void testReadOnlyCopy(SegmentKind kind1, SegmentKind kind2) { MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE); MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE); // check failure with read-only dest - MemorySegment.copy(s1, Type.BYTE.layout, 0, s2.asReadOnly(), Type.BYTE.layout, 0, 0); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(s1, Type.BYTE.layout, 0, s2.asReadOnly(), Type.BYTE.layout, 0, 0); + }); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Attempt to write a read-only segment.*") + @Test public void badCopy6Arg() { try (Arena scope = Arena.ofConfined()) { MemorySegment dest = scope.allocate(ValueLayout.JAVA_INT).asReadOnly(); - MemorySegment.copy(new int[1],0, dest, ValueLayout.JAVA_INT, 0 ,1); // should throw + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(new int[1],0, dest, ValueLayout.JAVA_INT, 0 ,1); + }); + assertTrue(e.getMessage().matches(".*Attempt to write a read-only segment.*")); } } - @Test(expectedExceptions = IndexOutOfBoundsException.class, dataProvider = "types") + @ParameterizedTest + @MethodSource("types") public void testBadOverflow(Type type) { - if (type.layout.byteSize() > 1) { - MemorySegment segment = MemorySegment.ofArray(new byte[100]); + Assumptions.assumeTrue(type.layout.byteSize() > 1, "Byte layouts do not overflow"); + MemorySegment segment = MemorySegment.ofArray(new byte[100]); + assertThrows(IndexOutOfBoundsException.class, () -> { MemorySegment.copy(segment, type.layout, 0, segment, type.layout, 0, Long.MAX_VALUE); - } else { - throw new SkipException("Byte layouts do not overflow"); - } + }); } - @Test(dataProvider = "segmentKindsAndTypes") + @ParameterizedTest + @MethodSource("segmentKindsAndTypes") public void testElementCopy(SegmentKind kind1, SegmentKind kind2, Type type1, Type type2) { MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE); MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE); @@ -220,16 +237,20 @@ public void testElementCopy(SegmentKind kind1, SegmentKind kind2, Type type1, Ty } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testHyperAlignedSrc() { MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); - MemorySegment.copy(segment, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(segment, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testHyperAlignedDst() { MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); - MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, segment, 0, 4); + assertThrows(IllegalArgumentException.class, () -> { + MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, segment, 0, 4); + }); } @Test @@ -334,7 +355,7 @@ void set(MemorySegment segment, long offset, int index, int val) { } void check(MemorySegment segment, long offset, int index, int val) { - assertEquals(handle().get(segment, offset + (index * size())), valueConverter.apply(val)); + assertEquals(valueConverter.apply(val), handle().get(segment, offset + (index * size()))); } } @@ -353,7 +374,6 @@ MemorySegment makeSegment(int size) { } } - @DataProvider static Object[][] segmentKinds() { List cases = new ArrayList<>(); for (SegmentKind kind1 : SegmentKind.values()) { @@ -364,7 +384,6 @@ static Object[][] segmentKinds() { return cases.toArray(Object[][]::new); } - @DataProvider static Object[][] conjunctSegments() { List cases = new ArrayList<>(); for (SegmentKind kind : SegmentKind.values()) { @@ -386,14 +405,12 @@ static Object[][] conjunctSegments() { return cases.toArray(Object[][]::new); } - @DataProvider static Object[][] types() { return Arrays.stream(Type.values()) .map(t -> new Object[] { t }) .toArray(Object[][]::new); } - @DataProvider static Object[][] segmentKindsAndTypes() { List cases = new ArrayList<>(); for (Object[] segmentKinds : segmentKinds()) { diff --git a/test/jdk/java/foreign/TestSegmentOverlap.java b/test/jdk/java/foreign/TestSegmentOverlap.java index 817d79b08ccf..bbade2fc4fff 100644 --- a/test/jdk/java/foreign/TestSegmentOverlap.java +++ b/test/jdk/java/foreign/TestSegmentOverlap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm TestSegmentOverlap + * @run junit/othervm TestSegmentOverlap */ import java.io.File; @@ -37,11 +37,14 @@ import java.util.function.Supplier; import java.lang.foreign.MemorySegment; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; import static java.lang.System.out; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSegmentOverlap { static Path tempPath; @@ -58,7 +61,6 @@ public class TestSegmentOverlap { } } - @DataProvider(name = "segmentFactories") public Object[][] segmentFactories() { List> l = List.of( () -> Arena.ofAuto().allocate(16, 1), @@ -80,7 +82,8 @@ public Object[][] segmentFactories() { return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } - @Test(dataProvider="segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testBasic(Supplier segmentSupplier) { var s1 = segmentSupplier.get(); var s2 = segmentSupplier.get(); @@ -92,39 +95,41 @@ public void testBasic(Supplier segmentSupplier) { assertTrue(s1.asOverlappingSlice(sOther).isEmpty()); } - @Test(dataProvider="segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testIdentical(Supplier segmentSupplier) { var s1 = segmentSupplier.get(); var s2 = s1.asReadOnly(); out.format("testIdentical s1:%s, s2:%s\n", s1, s2); - assertEquals(s1.asOverlappingSlice(s2).get().byteSize(), s1.byteSize()); - assertEquals(s1.asOverlappingSlice(s2).get().scope(), s1.scope()); + assertEquals(s1.byteSize(), s1.asOverlappingSlice(s2).get().byteSize()); + assertEquals(s1.scope(), s1.asOverlappingSlice(s2).get().scope()); - assertEquals(s2.asOverlappingSlice(s1).get().byteSize(), s2.byteSize()); - assertEquals(s2.asOverlappingSlice(s1).get().scope(), s2.scope()); + assertEquals(s2.byteSize(), s2.asOverlappingSlice(s1).get().byteSize()); + assertEquals(s2.scope(), s2.asOverlappingSlice(s1).get().scope()); if (s1.isNative()) { - assertEquals(s1.asOverlappingSlice(s2).get().address(), s1.address()); - assertEquals(s2.asOverlappingSlice(s1).get().address(), s2.address()); + assertEquals(s1.address(), s1.asOverlappingSlice(s2).get().address()); + assertEquals(s2.address(), s2.asOverlappingSlice(s1).get().address()); } } - @Test(dataProvider="segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testSlices(Supplier segmentSupplier) { MemorySegment s1 = segmentSupplier.get(); MemorySegment s2 = segmentSupplier.get(); for (int offset = 0 ; offset < 4 ; offset++) { MemorySegment slice = s1.asSlice(offset); out.format("testSlices s1:%s, s2:%s, slice:%s, offset:%d\n", s1, s2, slice, offset); - assertEquals(s1.asOverlappingSlice(slice).get().byteSize(), s1.byteSize() - offset); - assertEquals(s1.asOverlappingSlice(slice).get().scope(), s1.scope()); + assertEquals(s1.byteSize() - offset, s1.asOverlappingSlice(slice).get().byteSize()); + assertEquals(s1.scope(), s1.asOverlappingSlice(slice).get().scope()); - assertEquals(slice.asOverlappingSlice(s1).get().byteSize(), slice.byteSize()); - assertEquals(slice.asOverlappingSlice(s1).get().scope(), slice.scope()); + assertEquals(slice.byteSize(), slice.asOverlappingSlice(s1).get().byteSize()); + assertEquals(slice.scope(), slice.asOverlappingSlice(s1).get().scope()); if (s1.isNative()) { - assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address() + offset); - assertEquals(slice.asOverlappingSlice(s1).get().address(), slice.address()); + assertEquals(s1.address() + offset, s1.asOverlappingSlice(slice).get().address()); + assertEquals(slice.address(), slice.asOverlappingSlice(s1).get().address()); } assertTrue(s2.asOverlappingSlice(slice).isEmpty()); } diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index e9f3e8a87cc2..a8d3b73f54e1 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,11 @@ * @test * @requires vm.bits == 64 * @modules java.base/sun.nio.ch - * @run testng/othervm -Xmx4G -XX:MaxDirectMemorySize=1M --enable-native-access=ALL-UNNAMED TestSegments + * @run junit/othervm -Xmx4G -XX:MaxDirectMemorySize=1M --enable-native-access=ALL-UNNAMED TestSegments */ import java.lang.foreign.*; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; @@ -45,20 +43,29 @@ import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSegments { - @Test(dataProvider = "badSizeAndAlignments", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("sizesAndAlignments") public void testBadAllocateAlign(long size, long align) { - Arena.ofAuto().allocate(size, align); + assertThrows(IllegalArgumentException.class, () -> { + Arena.ofAuto().allocate(size, align); + }); } @Test public void testZeroLengthNativeSegment() { try (Arena arena = Arena.ofConfined()) { var segment = arena.allocate(0, 1); - assertEquals(segment.byteSize(), 0); + assertEquals(0, segment.byteSize()); if (segment.address() == 0) { fail("Segment address is zero"); } @@ -67,14 +74,14 @@ public void testZeroLengthNativeSegment() { } MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT); segment = arena.allocate(seq); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.address() % seq.byteAlignment(), 0); + assertEquals(0, segment.byteSize()); + assertEquals(0, segment.address() % seq.byteAlignment()); segment = arena.allocate(0, 4); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.address() % 4, 0); + assertEquals(0, segment.byteSize()); + assertEquals(0, segment.address() % 4); MemorySegment rawAddress = MemorySegment.ofAddress(segment.address()); - assertEquals(rawAddress.byteSize(), 0); - assertEquals(rawAddress.address() % 4, 0); + assertEquals(0, rawAddress.byteSize()); + assertEquals(0, rawAddress.address() % 4); } } @@ -83,7 +90,7 @@ public void testZeroLengthNativeSegmentHyperAligned() { long byteAlignment = 1024; try (Arena arena = Arena.ofConfined()) { var segment = arena.allocate(0, byteAlignment); - assertEquals(segment.byteSize(), 0); + assertEquals(0, segment.byteSize()); if (segment.address() == 0) { fail("Segment address is zero"); } @@ -91,17 +98,21 @@ public void testZeroLengthNativeSegmentHyperAligned() { } } - - @Test(expectedExceptions = { OutOfMemoryError.class, - IllegalArgumentException.class }) + @Test public void testAllocateTooBig() { - Arena.ofAuto().allocate(Long.MAX_VALUE, 1); + // One of two ex. types may be thrown. Throwable is common ancestor. + Throwable t = assertThrows(Throwable.class, + () -> Arena.ofAuto().allocate(Long.MAX_VALUE, 1)); + // must be either + assertTrue(t instanceof OutOfMemoryError || t instanceof IllegalArgumentException); } - @Test(expectedExceptions = OutOfMemoryError.class) + @Test public void testNativeAllocationTooBig() { - Arena scope = Arena.ofAuto(); - MemorySegment segment = scope.allocate(1024L * 1024 * 8 * 2, 1); // 2M + assertThrows(OutOfMemoryError.class, () -> { + Arena scope = Arena.ofAuto(); + MemorySegment segment = scope.allocate(1024L * 1024 * 8 * 2, 1); // 2M + }); } @Test @@ -127,88 +138,91 @@ public void testSlices() { for (int offset = 0 ; offset < 10 ; offset++) { MemorySegment slice = segment.asSlice(offset); for (long i = offset ; i < 10 ; i++) { - assertEquals( - byteHandle.get(segment, i), - byteHandle.get(slice, i - offset) + assertEquals( byteHandle.get(slice, i - offset), byteHandle.get(segment, i) ); } } } } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testDerivedScopes(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); assertEquals(segment.scope(), segment.scope()); // one level - assertEquals(segment.asSlice(0).scope(), segment.scope()); - assertEquals(segment.asReadOnly().scope(), segment.scope()); + assertEquals(segment.scope(), segment.asSlice(0).scope()); + assertEquals(segment.scope(), segment.asReadOnly().scope()); // two levels - assertEquals(segment.asSlice(0).asReadOnly().scope(), segment.scope()); - assertEquals(segment.asReadOnly().asSlice(0).scope(), segment.scope()); + assertEquals(segment.scope(), segment.asSlice(0).asReadOnly().scope()); + assertEquals(segment.scope(), segment.asReadOnly().asSlice(0).scope()); // check fresh every time MemorySegment another = segmentSupplier.get(); - assertNotEquals(segment.scope(), another.scope()); + assertNotEquals(another.scope(), segment.scope()); } @Test public void testEqualsOffHeap() { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(100, 1); - assertEquals(segment, segment.asReadOnly()); - assertEquals(segment, segment.asSlice(0, 100)); - assertNotEquals(segment, segment.asSlice(10, 90)); - assertEquals(segment, segment.asSlice(0, 90)); - assertEquals(segment, MemorySegment.ofAddress(segment.address())); + assertEquals(segment.asReadOnly(), segment); + assertEquals(segment.asSlice(0, 100), segment); + assertNotEquals(segment.asSlice(10, 90), segment); + assertEquals(segment.asSlice(0, 90), segment); + assertEquals(MemorySegment.ofAddress(segment.address()), segment); MemorySegment segment2 = arena.allocate(100, 1); - assertNotEquals(segment, segment2); + assertNotEquals(segment2, segment); } } @Test public void testEqualsOnHeap() { MemorySegment segment = MemorySegment.ofArray(new byte[100]); - assertEquals(segment, segment.asReadOnly()); - assertEquals(segment, segment.asSlice(0, 100)); - assertNotEquals(segment, segment.asSlice(10, 90)); - assertEquals(segment, segment.asSlice(0, 90)); + assertEquals(segment.asReadOnly(), segment); + assertEquals(segment.asSlice(0, 100), segment); + assertNotEquals(segment.asSlice(10, 90), segment); + assertEquals(segment.asSlice(0, 90), segment); MemorySegment segment2 = MemorySegment.ofArray(new byte[100]); - assertNotEquals(segment, segment2); + assertNotEquals(segment2, segment); } @Test public void testHashCodeOffHeap() { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(100, 1); - assertEquals(segment.hashCode(), segment.asReadOnly().hashCode()); - assertEquals(segment.hashCode(), segment.asSlice(0, 100).hashCode()); - assertEquals(segment.hashCode(), segment.asSlice(0, 90).hashCode()); - assertEquals(segment.hashCode(), MemorySegment.ofAddress(segment.address()).hashCode()); + assertEquals(segment.asReadOnly().hashCode(), segment.hashCode()); + assertEquals(segment.asSlice(0, 100).hashCode(), segment.hashCode()); + assertEquals(segment.asSlice(0, 90).hashCode(), segment.hashCode()); + assertEquals(MemorySegment.ofAddress(segment.address()).hashCode(), segment.hashCode()); } } @Test public void testHashCodeOnHeap() { MemorySegment segment = MemorySegment.ofArray(new byte[100]); - assertEquals(segment.hashCode(), segment.asReadOnly().hashCode()); - assertEquals(segment.hashCode(), segment.asSlice(0, 100).hashCode()); - assertEquals(segment.hashCode(), segment.asSlice(0, 90).hashCode()); + assertEquals(segment.asReadOnly().hashCode(), segment.hashCode()); + assertEquals(segment.asSlice(0, 100).hashCode(), segment.hashCode()); + assertEquals(segment.asSlice(0, 90).hashCode(), segment.hashCode()); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSmallSegmentMax() { long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when cast to int Arena scope = Arena.ofAuto(); MemorySegment memorySegment = scope.allocate(10, 1); - memorySegment.get(JAVA_INT, offset); + assertThrows(IndexOutOfBoundsException.class, () -> { + memorySegment.get(JAVA_INT, offset); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSmallSegmentMin() { long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when cast to int Arena scope = Arena.ofAuto(); MemorySegment memorySegment = scope.allocate(10L, 1); - memorySegment.get(JAVA_INT, offset); + assertThrows(IndexOutOfBoundsException.class, () -> { + memorySegment.get(JAVA_INT, offset); + }); } @Test @@ -241,13 +255,13 @@ public void testSegmentSliceOOBMessage() { } } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testAccessModesOfFactories(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); assertFalse(segment.isReadOnly()); } - @DataProvider(name = "scopes") public Object[][] scopes() { return new Object[][] { { Arena.ofAuto(), false }, @@ -257,14 +271,16 @@ public Object[][] scopes() { }; } - @Test(dataProvider = "scopes") + @ParameterizedTest(autoCloseArguments = false) + @MethodSource("scopes") public void testIsAccessibleBy(Arena arena, boolean isConfined) { MemorySegment segment = MemorySegment.NULL.reinterpret(arena, null); assertTrue(segment.isAccessibleBy(Thread.currentThread())); assertTrue(segment.isAccessibleBy(new Thread()) != isConfined); } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testToString(Supplier segmentSupplier) { var segment = segmentSupplier.get(); String s = segment.toString(); @@ -281,7 +297,6 @@ public void testToString(Supplier segmentSupplier) { assertFalse(s.contains("Optional")); } - @DataProvider(name = "segmentFactories") public Object[][] segmentFactories() { List> l = List.of( () -> MemorySegment.ofArray(new byte[] { 0x00, 0x01, 0x02, 0x03 }), @@ -302,7 +317,8 @@ public Object[][] segmentFactories() { return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testFill(Supplier segmentSupplier) { VarHandle byteHandle = ValueLayout.JAVA_BYTE.varHandle(); @@ -310,27 +326,28 @@ public void testFill(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); segment.fill(value); for (long l = 0; l < segment.byteSize(); l++) { - assertEquals((byte) byteHandle.get(segment, l), value); + assertEquals(value, (byte) byteHandle.get(segment, l)); } // fill a slice var sliceSegment = segment.asSlice(1, segment.byteSize() - 2).fill((byte) ~value); for (long l = 0; l < sliceSegment.byteSize(); l++) { - assertEquals((byte) byteHandle.get(sliceSegment, l), ~value); + assertEquals(~value, (byte) byteHandle.get(sliceSegment, l)); } // assert enclosing slice - assertEquals((byte) byteHandle.get(segment, 0L), value); + assertEquals(value, (byte) byteHandle.get(segment, 0L)); for (long l = 1; l < segment.byteSize() - 2; l++) { - assertEquals((byte) byteHandle.get(segment, l), (byte) ~value); + assertEquals((byte) ~value, (byte) byteHandle.get(segment, l)); } - assertEquals((byte) byteHandle.get(segment, segment.byteSize() - 1L), value); + assertEquals(value, (byte) byteHandle.get(segment, segment.byteSize() - 1L)); } } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testHeapBase(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); - assertEquals(segment.isNative(), !segment.heapBase().isPresent()); + assertEquals(!segment.heapBase().isPresent(), segment.isNative()); segment = segment.asReadOnly(); assertTrue(segment.heapBase().isEmpty()); } @@ -339,7 +356,7 @@ public void testHeapBase(Supplier segmentSupplier) { public void testScopeConfinedArena() { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(100); - assertEquals(segment.scope(), arena.scope()); + assertEquals(arena.scope(), segment.scope()); } } @@ -347,7 +364,7 @@ public void testScopeConfinedArena() { public void testScopeSharedArena() { try (Arena arena = Arena.ofShared()) { MemorySegment segment = arena.allocate(100); - assertEquals(segment.scope(), arena.scope()); + assertEquals(arena.scope(), segment.scope()); } } @@ -355,29 +372,36 @@ public void testScopeSharedArena() { public void testScopeAutoArena() { Arena arena = Arena.ofAuto(); MemorySegment segment = arena.allocate(100); - assertEquals(segment.scope(), arena.scope()); + assertEquals(arena.scope(), segment.scope()); } @Test public void testScopeGlobalArena() { Arena arena = Arena.global(); MemorySegment segment = arena.allocate(100); - assertEquals(segment.scope(), arena.scope()); + assertEquals(arena.scope(), segment.scope()); } - @Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("segmentFactories") public void testFillIllegalAccessMode(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); - segment.asReadOnly().fill((byte) 0xFF); + assertThrows(IllegalArgumentException.class, () -> { + segment.asReadOnly().fill((byte) 0xFF); + }); } - @Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class) + @ParameterizedTest + @MethodSource("segmentFactories") public void testFromStringIllegalAccessMode(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); - segment.asReadOnly().setString(0, "a"); + assertThrows(IllegalArgumentException.class, () -> { + segment.asReadOnly().setString(0, "a"); + }); } - @Test(dataProvider = "segmentFactories") + @ParameterizedTest + @MethodSource("segmentFactories") public void testFillThread(Supplier segmentSupplier) throws Exception { MemorySegment segment = segmentSupplier.get(); AtomicReference exception = new AtomicReference<>(); @@ -407,12 +431,13 @@ public void testFillEmpty() { MemorySegment.ofBuffer(ByteBuffer.allocateDirect(0)).fill((byte) 0xFF); } - @Test(dataProvider = "heapFactories") + @ParameterizedTest + @MethodSource("heapFactories") public void testVirtualizedBaseAddress(IntFunction heapSegmentFactory, int factor) { MemorySegment segment = heapSegmentFactory.apply(10); - assertEquals(segment.address(), 0); // base address should be zero (no leaking of impl details) + assertEquals(0, segment.address()); // base address should be zero (no leaking of impl details) MemorySegment end = segment.asSlice(segment.byteSize(), 0); - assertEquals(end.address(), segment.byteSize()); // end address should be equal to segment byte size + assertEquals(segment.byteSize(), end.address()); // end address should be equal to segment byte size } @Test @@ -420,18 +445,18 @@ void testReinterpret() { AtomicInteger counter = new AtomicInteger(); try (Arena arena = Arena.ofConfined()){ // check size - assertEquals(MemorySegment.ofAddress(42).reinterpret(100).byteSize(), 100); - assertEquals(MemorySegment.ofAddress(42).reinterpret(100, Arena.ofAuto(), null).byteSize(), 100); + assertEquals(100, MemorySegment.ofAddress(42).reinterpret(100).byteSize()); + assertEquals(100, MemorySegment.ofAddress(42).reinterpret(100, Arena.ofAuto(), null).byteSize()); // check scope and cleanup - assertEquals(MemorySegment.ofAddress(42).reinterpret(100, arena, s -> counter.incrementAndGet()).scope(), arena.scope()); - assertEquals(MemorySegment.ofAddress(42).reinterpret(arena, _ -> counter.incrementAndGet()).scope(), arena.scope()); + assertEquals(arena.scope(), MemorySegment.ofAddress(42).reinterpret(100, arena, s -> counter.incrementAndGet()).scope()); + assertEquals(arena.scope(), MemorySegment.ofAddress(42).reinterpret(arena, _ -> counter.incrementAndGet()).scope()); // check read-only state assertFalse(MemorySegment.ofAddress(42).reinterpret(100).isReadOnly()); assertTrue(MemorySegment.ofAddress(42).asReadOnly().reinterpret(100).isReadOnly()); assertTrue(MemorySegment.ofAddress(42).asReadOnly().reinterpret(100, Arena.ofAuto(), null).isReadOnly()); assertTrue(MemorySegment.ofAddress(42).asReadOnly().reinterpret(arena, _ -> counter.incrementAndGet()).isReadOnly()); } - assertEquals(counter.get(), 3); + assertEquals(3, counter.get()); } @Test @@ -477,8 +502,8 @@ void testThrowInCleanup() { thrown = ex; } assertNotNull(thrown); - assertEquals(counter.get(), 1); - assertEquals(thrown.getSuppressed().length, 19); + assertEquals(1, counter.get()); + assertEquals(19, thrown.getSuppressed().length); Throwable[] errors = new IllegalArgumentException[20]; assertTrue(thrown instanceof IllegalArgumentException); errors[0] = thrown; @@ -512,12 +537,11 @@ void testThrowInCleanupSame() { } catch (RuntimeException ex) { thrown = ex; } - assertEquals(thrown, iae); - assertEquals(counter.get(), 1); - assertEquals(thrown.getSuppressed().length, 0); + assertEquals(iae, thrown); + assertEquals(1, counter.get()); + assertEquals(0, thrown.getSuppressed().length); } - @DataProvider(name = "badSizeAndAlignments") public Object[][] sizesAndAlignments() { return new Object[][] { { -1, 8 }, @@ -526,7 +550,6 @@ public Object[][] sizesAndAlignments() { }; } - @DataProvider(name = "heapFactories") public Object[][] heapFactories() { return new Object[][] { { (IntFunction) size -> MemorySegment.ofArray(new byte[size]), 1 }, diff --git a/test/jdk/java/foreign/TestSharedAccess.java b/test/jdk/java/foreign/TestSharedAccess.java index 9823f6f0bbfb..093f20cd96aa 100644 --- a/test/jdk/java/foreign/TestSharedAccess.java +++ b/test/jdk/java/foreign/TestSharedAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestSharedAccess + * @run junit/othervm --enable-native-access=ALL-UNNAMED TestSharedAccess */ import java.lang.foreign.*; @@ -37,9 +37,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestSharedAccess { @@ -74,7 +73,7 @@ public void testShared() throws Throwable { for (Spliterator spliterator : spliterators) { threads.add(new Thread(() -> { spliterator.tryAdvance(local -> { - assertEquals(getInt(local), 42); + assertEquals(42, getInt(local)); accessCount.incrementAndGet(); }); })); @@ -87,7 +86,7 @@ public void testShared() throws Throwable { throw new IllegalStateException(e); } }); - assertEquals(accessCount.get(), 1024); + assertEquals(1024, accessCount.get()); } } @@ -96,11 +95,11 @@ public void testSharedUnsafe() throws Throwable { try (Arena arena = Arena.ofShared()) { MemorySegment s = arena.allocate(4, 1);; setInt(s, 42); - assertEquals(getInt(s), 42); + assertEquals(42, getInt(s)); List threads = new ArrayList<>(); for (int i = 0 ; i < 1000 ; i++) { threads.add(new Thread(() -> { - assertEquals(getInt(s), 42); + assertEquals(42, getInt(s)); })); } threads.forEach(Thread::start); diff --git a/test/jdk/java/foreign/TestSlices.java b/test/jdk/java/foreign/TestSlices.java index 88fe98cc847e..d2ba96ae94ba 100644 --- a/test/jdk/java/foreign/TestSlices.java +++ b/test/jdk/java/foreign/TestSlices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,17 @@ import java.util.ArrayList; import java.util.List; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test - * @run testng/othervm -Xverify:all TestSlices + * @run junit/othervm -Xverify:all TestSlices */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSlices { static MemoryLayout LAYOUT = MemoryLayout.sequenceLayout(2, @@ -45,7 +49,8 @@ public class TestSlices { static VarHandle VH_ALL = LAYOUT.varHandle( MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement()); - @Test(dataProvider = "slices") + @ParameterizedTest + @MethodSource("slices") public void testSlices(VarHandle handle, int lo, int hi, int[] values) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(LAYOUT);; @@ -60,12 +65,13 @@ public void testSlices(VarHandle handle, int lo, int hi, int[] values) { } } - @Test(dataProvider = "slices") + @ParameterizedTest + @MethodSource("slices") public void testSliceBadIndex(VarHandle handle, int lo, int hi, int[] values) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(LAYOUT);; - assertThrows(() -> handle.get(segment, 0L, lo, 0)); - assertThrows(() -> handle.get(segment, 0L, 0, hi)); + assertThrows(Throwable.class, () -> handle.get(segment, 0L, lo, 0)); + assertThrows(Throwable.class, () -> handle.get(segment, 0L, 0, hi)); } } @@ -74,54 +80,71 @@ static void checkSlice(MemorySegment segment, VarHandle handle, long i_max, long for (long i = 0 ; i < i_max ; i++) { for (long j = 0 ; j < j_max ; j++) { int x = (int) handle.get(segment, 0L, i, j); - assertEquals(x, values[index++]); + assertEquals(values[index++], x); } } - assertEquals(index, values.length); + assertEquals(values.length, index); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceNegativeOffset() { - MemorySegment.ofArray(new byte[100]).asSlice(-1); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(-1); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceNegativeOffsetGoodSize() { - MemorySegment.ofArray(new byte[100]).asSlice(-1, 10); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(-1, 10); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceGoodOffsetNegativeSize() { - MemorySegment.ofArray(new byte[100]).asSlice(10, -1); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(10, -1); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceNegativeOffsetGoodLayout() { - MemorySegment.ofArray(new byte[100]).asSlice(-1, ValueLayout.JAVA_INT); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(-1, ValueLayout.JAVA_INT); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceOffsetTooBig() { - MemorySegment.ofArray(new byte[100]).asSlice(120); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(120); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceOffsetTooBigSizeGood() { - MemorySegment.ofArray(new byte[100]).asSlice(120, 0); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(120, 0); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceOffsetOkSizeTooBig() { - MemorySegment.ofArray(new byte[100]).asSlice(0, 120); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]).asSlice(0, 120); + }); } - @Test(expectedExceptions = IndexOutOfBoundsException.class) + @Test public void testSliceLayoutTooBig() { - MemorySegment.ofArray(new byte[100]) - .asSlice(0, MemoryLayout.sequenceLayout(120, ValueLayout.JAVA_BYTE)); + assertThrows(IndexOutOfBoundsException.class, () -> { + MemorySegment.ofArray(new byte[100]) + .asSlice(0, MemoryLayout.sequenceLayout(120, ValueLayout.JAVA_BYTE)); + }); } - @Test(dataProvider = "segmentsAndLayouts") + @ParameterizedTest + @MethodSource("segmentsAndLayouts") public void testSliceAlignment(MemorySegment segment, long alignment, ValueLayout layout) { boolean badAlign = layout.byteAlignment() > alignment; try { @@ -149,7 +172,6 @@ public void testSliceAlignmentPowerOfTwo() { } } - @DataProvider(name = "slices") static Object[][] slices() { return new Object[][] { // x @@ -169,7 +191,6 @@ static Object[][] slices() { }; } - @DataProvider(name = "segmentsAndLayouts") static Object[][] segmentsAndLayouts() { List segmentsAndLayouts = new ArrayList<>(); for (SegmentKind sk : SegmentKind.values()) { diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index 285e8ab27ea0..074615218c91 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng TestSpliterator + * @run junit TestSpliterator */ import java.lang.foreign.*; @@ -35,15 +35,19 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.LongStream; -import org.testng.annotations.*; - -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSpliterator { final static int CARRIER_SIZE = 4; - @Test(dataProvider = "splits") + @ParameterizedTest + @MethodSource("splits") public void testSum(int size, int threshold) { SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT); @@ -56,17 +60,17 @@ public void testSum(int size, int threshold) { long expected = LongStream.range(0, layout.elementCount()).sum(); //serial long serial = sum(0, segment); - assertEquals(serial, expected); + assertEquals(expected, serial); //parallel counted completer long parallelCounted = new SumSegmentCounted(null, segment.spliterator(layout.elementLayout()), threshold).invoke(); - assertEquals(parallelCounted, expected); + assertEquals(expected, parallelCounted); //parallel recursive action long parallelRecursive = new SumSegmentRecursive(segment.spliterator(layout.elementLayout()), threshold).invoke(); - assertEquals(parallelRecursive, expected); + assertEquals(expected, parallelRecursive); //parallel stream long streamParallel = segment.elements(layout.elementLayout()).parallel() .reduce(0L, TestSpliterator::sumSingle, Long::sum); - assertEquals(streamParallel, expected); + assertEquals(expected, streamParallel); } } @@ -86,35 +90,39 @@ public void testSumSameThread() { AtomicLong spliteratorSum = new AtomicLong(); segment.spliterator(layout.elementLayout()) .forEachRemaining(s -> spliteratorSum.addAndGet(sumSingle(0L, s))); - assertEquals(spliteratorSum.get(), expected); + assertEquals(expected, spliteratorSum.get()); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadSpliteratorElementSizeTooBig() { - Arena scope = Arena.ofAuto(); - scope.allocate(2, 1) - .spliterator(ValueLayout.JAVA_INT); + MemorySegment segment = Arena.ofAuto().allocate(2, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.spliterator(ValueLayout.JAVA_INT); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadStreamElementSizeTooBig() { - Arena scope = Arena.ofAuto(); - scope.allocate(2, 1) - .elements(ValueLayout.JAVA_INT); + MemorySegment segment = Arena.ofAuto().allocate(2, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.elements(ValueLayout.JAVA_INT); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadSpliteratorElementSizeNotMultiple() { - Arena scope = Arena.ofAuto(); - scope.allocate(7, 1) - .spliterator(ValueLayout.JAVA_INT); + MemorySegment segment = Arena.ofAuto().allocate(7, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.spliterator(ValueLayout.JAVA_INT); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadStreamElementSizeNotMultiple() { - Arena scope = Arena.ofAuto(); - scope.allocate(7, 1) - .elements(ValueLayout.JAVA_INT); + MemorySegment segment = Arena.ofAuto().allocate(7, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.elements(ValueLayout.JAVA_INT); + }); } @Test @@ -131,18 +139,20 @@ public void testStreamElementSizeMultipleButNotPowerOfTwo() { .elements(ValueLayout.JAVA_INT); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadSpliteratorElementSizeZero() { - Arena scope = Arena.ofAuto(); - scope.allocate(7, 1) - .spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment segment = Arena.ofAuto().allocate(7, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testBadStreamElementSizeZero() { - Arena scope = Arena.ofAuto(); - scope.allocate(7, 1) - .elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment segment = Arena.ofAuto().allocate(7, 1); + assertThrows(IllegalArgumentException.class, () -> { + segment.elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + }); } @Test @@ -155,9 +165,9 @@ public void testHyperAligned() { Collections.nCopies(Math.toIntExact(bigByteAlign), ValueLayout.JAVA_BYTE).toArray(MemoryLayout[]::new)) .withByteAlignment(bigByteAlign); SequenceLayout layout = MemoryLayout.sequenceLayout(2, elementLayout); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> segment.elements(layout)); - assertEquals(iae.getMessage(), "Incompatible alignment constraints"); + assertEquals("Incompatible alignment constraints", iae.getMessage()); } static long sumSingle(long acc, MemorySegment segment) { @@ -239,7 +249,6 @@ protected Long compute() { } } - @DataProvider(name = "splits") public Object[][] splits() { return new Object[][] { { 10, 1 }, diff --git a/test/jdk/java/foreign/TestStringEncoding.java b/test/jdk/java/foreign/TestStringEncoding.java index e9e47420a684..c2a9131941bf 100644 --- a/test/jdk/java/foreign/TestStringEncoding.java +++ b/test/jdk/java/foreign/TestStringEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,17 +42,22 @@ import jdk.internal.foreign.AbstractMemorySegmentImpl; import jdk.internal.foreign.StringSupport; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test * @modules java.base/jdk.internal.foreign - * @run testng TestStringEncoding + * @run junit TestStringEncoding */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestStringEncoding { @Test @@ -61,7 +66,7 @@ public void emptySegment() { for (Arena arena : arenas()) { try (arena) { var segment = arena.allocate(0); - var e = expectThrows(IndexOutOfBoundsException.class, () -> + var e = assertThrows(IndexOutOfBoundsException.class, () -> segment.getString(0, charset)); assertTrue(e.getMessage().contains("No null terminator found")); } @@ -69,7 +74,8 @@ public void emptySegment() { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testStrings(String testString) { for (Charset charset : Charset.availableCharsets().values()) { if (isStandard(charset)) { @@ -89,11 +95,11 @@ public void testStrings(String testString) { testString.getBytes(charset).length + terminatorSize; - assertEquals(text.byteSize(), expectedByteLength); + assertEquals(expectedByteLength, text.byteSize()); String roundTrip = text.getString(0, charset); if (charset.newEncoder().canEncode(testString)) { - assertEquals(roundTrip, testString); + assertEquals(testString, roundTrip); } } } @@ -103,7 +109,8 @@ public void testStrings(String testString) { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testStringsLength(String testString) { if (!testString.isEmpty()) { for (Charset charset : Charset.availableCharsets().values()) { @@ -112,10 +119,10 @@ public void testStringsLength(String testString) { try (arena) { MemorySegment text = arena.allocateFrom(testString, charset, 0, testString.length()); long length = text.byteSize(); - assertEquals(length, testString.getBytes(charset).length); + assertEquals(testString.getBytes(charset).length, length); String roundTrip = text.getString(0, charset, length); if (charset.newEncoder().canEncode(testString)) { - assertEquals(roundTrip, testString); + assertEquals(testString, roundTrip); } } } @@ -124,7 +131,8 @@ public void testStringsLength(String testString) { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testStringsCopy(String testString) { if (!testString.isEmpty()) { for (Charset charset : Charset.availableCharsets().values()) { @@ -136,7 +144,7 @@ public void testStringsCopy(String testString) { MemorySegment.copy(testString, charset, 0, text, 0, testString.length()); String roundTrip = text.getString(0, charset, bytes.length); if (charset.newEncoder().canEncode(testString)) { - assertEquals(roundTrip, testString); + assertEquals(testString, roundTrip); } } } @@ -237,7 +245,8 @@ public void testGetStringThrows() { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testStringsHeap(String testString) { for (Charset charset : singleByteCharsets()) { for (var arena : arenas()) { @@ -248,11 +257,11 @@ public void testStringsHeap(String testString) { int expectedByteLength = testString.getBytes(charset).length + 1; - assertEquals(text.byteSize(), expectedByteLength); + assertEquals(expectedByteLength, text.byteSize()); String roundTrip = text.getString(0, charset); if (charset.newEncoder().canEncode(testString)) { - assertEquals(roundTrip, testString); + assertEquals(testString, roundTrip); } } } @@ -264,7 +273,8 @@ MemorySegment toHeapSegment(MemorySegment segment) { return MemorySegment.ofArray(heapArray); } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void unboundedSegment(String testString) { testModifyingSegment(testString, standardCharsets(), @@ -272,7 +282,8 @@ public void unboundedSegment(String testString) { UnaryOperator.identity()); } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void unalignedSegmentSingleByte(String testString) { testModifyingSegment(testString, singleByteCharsets(), @@ -280,7 +291,8 @@ public void unalignedSegmentSingleByte(String testString) { s -> s.length() > 0 ? s.substring(1) : s); } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void expandedSegment(String testString) { try (var arena = Arena.ofConfined()) { for (int i = 0; i < Long.BYTES; i++) { @@ -309,7 +321,7 @@ public void testModifyingSegment(String testString, String roundTrip = text.getString(0, charset); String expected = stringMapper.apply(testString); if (charset.newEncoder().canEncode(testString)) { - assertEquals(roundTrip, expected); + assertEquals(expected, roundTrip); } } } @@ -330,14 +342,15 @@ public void testPeculiarContentSingleByte() { for (Charset charset : singleByteCharsets()) { var s = segment.getString(0, charset); var ref = referenceImpl(segment, 0, charset); - assertEquals(s, ref); + assertEquals(ref, s); } } } } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testOffset(String testString) { if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) { return; @@ -349,14 +362,15 @@ public void testOffset(String testString) { for (int i = 0; i < 3; i++) { String expected = testString.substring(i); String actual = inSegment.getString(i, charset); - assertEquals(actual, expected); + assertEquals(expected, actual); } } } } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testSubstringGetString(String testString) { if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) { return; @@ -370,7 +384,7 @@ public void testSubstringGetString(String testString) { // this test assumes single-byte charsets String roundTrip = text.getString(srcIndex, charset, numChars); String substring = testString.substring(srcIndex, srcIndex + numChars); - assertEquals(roundTrip, substring); + assertEquals(substring, roundTrip); } } } @@ -378,7 +392,8 @@ public void testSubstringGetString(String testString) { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testSubstringAllocate(String testString) { if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) { return; @@ -390,9 +405,9 @@ public void testSubstringAllocate(String testString) { for (int numChars = 0; numChars <= testString.length() - srcIndex; numChars++) { MemorySegment text = arena.allocateFrom(testString, charset, srcIndex, numChars); String substring = testString.substring(srcIndex, srcIndex + numChars); - assertEquals(text.byteSize(), substring.getBytes(charset).length); + assertEquals(substring.getBytes(charset).length, text.byteSize()); String roundTrip = text.getString(0, charset, text.byteSize()); - assertEquals(roundTrip, substring); + assertEquals(substring, roundTrip); } } } @@ -400,7 +415,8 @@ public void testSubstringAllocate(String testString) { } } - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void testSubstringCopy(String testString) { if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) { return; @@ -415,8 +431,8 @@ public void testSubstringCopy(String testString) { MemorySegment text = arena.allocate(JAVA_BYTE, length); long copied = MemorySegment.copy(testString, charset, srcIndex, text, 0, numChars); String roundTrip = text.getString(0, charset, length); - assertEquals(roundTrip, substring); - assertEquals(copied, length); + assertEquals(substring, roundTrip); + assertEquals(length, copied); } } } @@ -431,7 +447,8 @@ public void testSubstringCopy(String testString) { LINKER.defaultLookup().find("strcat").orElseThrow(), FunctionDescriptor.of(CHAR_POINTER, CHAR_POINTER, CHAR_POINTER)); - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void nativeSegFromNativeCall(String testString) { String addition = "123"; try (var arena = Arena.ofConfined()) { @@ -443,7 +460,7 @@ public void nativeSegFromNativeCall(String testString) { MemorySegment concatenation = (MemorySegment) STRCAT.invokeExact(destination, arena.allocateFrom(addition)); var actual = concatenation.getString(0); - assertEquals(actual, testString + addition); + assertEquals(testString + addition, actual); } catch (Throwable t) { throw new AssertionError(t); } @@ -469,7 +486,8 @@ public void segmentationFault() { // This test ensures that we do not address outside the segment even though there // are odd bytes at the end. - @Test(dataProvider = "strings") + @ParameterizedTest + @MethodSource("strings") public void offBoundaryTrailingBytes(String testString) { if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) { return; @@ -485,7 +503,7 @@ public void offBoundaryTrailingBytes(String testString) { inSegment.fill((byte) 1); for (int i = 0; i < 4; i++) { final int offset = i; - var e = expectThrows(IndexOutOfBoundsException.class, () -> inSegment.getString(offset, charset)); + var e = assertThrows(IndexOutOfBoundsException.class, () -> inSegment.getString(offset, charset)); assertTrue(e.getMessage().contains("No null terminator found")); } } @@ -516,12 +534,12 @@ public void chunked_strlen_byte() { segment.setAtIndex(JAVA_BYTE, len, (byte) 0); for (int j = 0; j < len; j++) { int actual = StringSupport.strlenByte((AbstractMemorySegmentImpl) segment, j, segment.byteSize()); - assertEquals(actual, len - j); + assertEquals(len - j, actual); } // Test end offset for (int j = 0; j < len - 1; j++) { final long toOffset = j; - expectThrows(IndexOutOfBoundsException.class, () -> + assertThrows(IndexOutOfBoundsException.class, () -> StringSupport.strlenByte((AbstractMemorySegmentImpl) segment, 0, toOffset)); } } @@ -546,7 +564,7 @@ public void chunked_strlen_short() { segment.setAtIndex(JAVA_SHORT, len, (short) 0); for (int j = 0; j < len; j++) { int actual = StringSupport.strlenShort((AbstractMemorySegmentImpl) segment, j * Short.BYTES, segment.byteSize()); - assertEquals(actual, (len - j) * Short.BYTES); + assertEquals((len - j) * Short.BYTES, actual); } } } @@ -570,35 +588,37 @@ public void strlen_int() { segment.setAtIndex(JAVA_INT, len, 0); for (int j = 0; j < len; j++) { int actual = StringSupport.strlenInt((AbstractMemorySegmentImpl) segment, j * Integer.BYTES, segment.byteSize()); - assertEquals(actual, (len - j) * Integer.BYTES); + assertEquals((len - j) * Integer.BYTES, actual); } } } } } - @Test(dataProvider = "charsetsAndSegments") + @ParameterizedTest + @MethodSource("charsetsAndSegments") public void testStringGetWithCharset(Charset charset, MemorySegment segment) { for (int offset = 0 ; offset < Long.BYTES ; offset++) { segment.getString(offset, charset); } } - @Test(dataProvider = "charsetsAndSegments") + @ParameterizedTest + @MethodSource("charsetsAndSegments") public void testStringSetWithCharset(Charset charset, MemorySegment segment) { for (int offset = 0 ; offset < Long.BYTES ; offset++) { segment.setString(offset, "H", charset); } } - @Test(dataProvider = "charsetsAndSegments") + @ParameterizedTest + @MethodSource("charsetsAndSegments") public void testStringAllocateFromWithCharset(Charset charset, MemorySegment segment) { for (int offset = 0 ; offset < Long.BYTES ; offset++) { SegmentAllocator.prefixAllocator(segment.asSlice(offset)).allocateFrom("H", charset); } } - @DataProvider public static Object[][] strings() { return new Object[][]{ {"testing"}, @@ -733,7 +753,6 @@ static MemorySegment[] heapSegments() { }; } - @DataProvider public static Object[][] charsetsAndSegments() { List values = new ArrayList<>(); for (Charset charset : standardCharsets()) { diff --git a/test/jdk/java/foreign/TestStringEncodingJumbo.java b/test/jdk/java/foreign/TestStringEncodingJumbo.java index bdae83bbd8b3..31f03768d36b 100644 --- a/test/jdk/java/foreign/TestStringEncodingJumbo.java +++ b/test/jdk/java/foreign/TestStringEncodingJumbo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,6 @@ * questions. */ -import org.testng.annotations.*; import java.io.IOException; import java.io.RandomAccessFile; @@ -34,7 +33,9 @@ import java.util.function.Consumer; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; /* * @test @@ -42,7 +43,7 @@ * @requires sun.arch.data.model == "64" * @requires vm.flavor != "zero" * - * @run testng/othervm/timeout=480 -Xmx6G TestStringEncodingJumbo + * @run junit/othervm/timeout=480 -Xmx6G TestStringEncodingJumbo */ public class TestStringEncodingJumbo { @@ -53,7 +54,7 @@ public void testJumboSegment() { segment.fill((byte) 1); segment.set(JAVA_BYTE, Integer.MAX_VALUE + 10L, (byte) 0); String big = segment.getString(100); - assertEquals(big.length(), Integer.MAX_VALUE - (100 - 10)); + assertEquals(Integer.MAX_VALUE - (100 - 10), big.length()); }); } diff --git a/test/jdk/java/foreign/TestStubAllocFailure.java b/test/jdk/java/foreign/TestStubAllocFailure.java index 8cd4a61626e7..99cd4b5eced2 100644 --- a/test/jdk/java/foreign/TestStubAllocFailure.java +++ b/test/jdk/java/foreign/TestStubAllocFailure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @library ../ /test/lib * @requires jdk.foreign.linker != "FALLBACK" * @requires vm.compMode != "Xcomp" - * @run testng/othervm/native/timeout=480 + * @run junit/othervm/native/timeout=480 * --enable-native-access=ALL-UNNAMED * TestStubAllocFailure */ @@ -39,9 +39,8 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import org.testng.annotations.Test; - -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; public class TestStubAllocFailure extends UpcallTestHelper { diff --git a/test/jdk/java/foreign/TestTypeAccess.java b/test/jdk/java/foreign/TestTypeAccess.java index 13d3eaf0c0f0..347c96905178 100644 --- a/test/jdk/java/foreign/TestTypeAccess.java +++ b/test/jdk/java/foreign/TestTypeAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,61 +24,75 @@ /* * @test - * @run testng TestTypeAccess + * @run junit TestTypeAccess */ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; -import org.testng.annotations.*; import java.lang.invoke.VarHandle; import java.lang.invoke.WrongMethodTypeException; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; + public class TestTypeAccess { static final VarHandle INT_HANDLE = ValueLayout.JAVA_INT.varHandle(); static final VarHandle ADDR_HANDLE = ValueLayout.ADDRESS.varHandle(); - @Test(expectedExceptions=ClassCastException.class) + @Test public void testMemoryAddressCoordinateAsString() { - int v = (int)INT_HANDLE.get("string", 0L); + assertThrows(ClassCastException.class, () -> { + int v = (int)INT_HANDLE.get("string", 0L); + }); } - @Test(expectedExceptions=WrongMethodTypeException.class) + @Test public void testMemoryCoordinatePrimitive() { - int v = (int)INT_HANDLE.get(1); + assertThrows(WrongMethodTypeException.class, () -> { + int v = (int)INT_HANDLE.get(1); + }); } - @Test(expectedExceptions=ClassCastException.class) + @Test public void testMemoryAddressValueGetAsString() { try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(8, 8); - String address = (String)ADDR_HANDLE.get(s, 0L); + assertThrows(ClassCastException.class, () -> { + String address = (String)ADDR_HANDLE.get(s, 0L); + }); } } - @Test(expectedExceptions=ClassCastException.class) + @Test public void testMemoryAddressValueSetAsString() { try (Arena arena = Arena.ofConfined()) { - MemorySegment s = arena.allocate(8, 8);; - ADDR_HANDLE.set(s, 0L, "string"); + MemorySegment s = arena.allocate(8, 8); + assertThrows(ClassCastException.class, () -> { + ADDR_HANDLE.set(s, 0L, "string"); + }); } } - @Test(expectedExceptions=WrongMethodTypeException.class) + @Test public void testMemoryAddressValueGetAsPrimitive() { try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(8, 8); - int address = (int)ADDR_HANDLE.get(s, 0L); + assertThrows(WrongMethodTypeException.class, () -> { + int address = (int)ADDR_HANDLE.get(s, 0L); + }); } } - @Test(expectedExceptions=WrongMethodTypeException.class) + @Test public void testMemoryAddressValueSetAsPrimitive() { try (Arena arena = Arena.ofConfined()) { - MemorySegment s = arena.allocate(8, 8);; - ADDR_HANDLE.set(s, 1); + MemorySegment s = arena.allocate(8, 8); + assertThrows(WrongMethodTypeException.class, () -> { + ADDR_HANDLE.set(s, 1); + }); } } diff --git a/test/jdk/java/foreign/TestUpcallAsync.java b/test/jdk/java/foreign/TestUpcallAsync.java index b912b1cd79e5..54a6651aa591 100644 --- a/test/jdk/java/foreign/TestUpcallAsync.java +++ b/test/jdk/java/foreign/TestUpcallAsync.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 * TestUpcallAsync */ import java.lang.foreign.*; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -45,6 +44,11 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallAsync extends TestUpcallBase { static { @@ -52,7 +56,8 @@ public class TestUpcallAsync extends TestUpcallBase { System.loadLibrary("AsyncInvokers"); } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testUpcallsAsync(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestUpcallBase.java b/test/jdk/java/foreign/TestUpcallBase.java index e768ade8577c..cf0249857be1 100644 --- a/test/jdk/java/foreign/TestUpcallBase.java +++ b/test/jdk/java/foreign/TestUpcallBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.junit.jupiter.api.TestInstance; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public abstract class TestUpcallBase extends CallGeneratorHelper { static FunctionDescriptor function(Ret ret, List params, List fields) { diff --git a/test/jdk/java/foreign/TestUpcallException.java b/test/jdk/java/foreign/TestUpcallException.java index beaa33f5e61f..5bf2aaa86e78 100644 --- a/test/jdk/java/foreign/TestUpcallException.java +++ b/test/jdk/java/foreign/TestUpcallException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,11 @@ * @library /test/lib * @build TestUpcallException * - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * TestUpcallException */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; import java.lang.foreign.Arena; @@ -43,16 +41,21 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallException extends UpcallTestHelper { - @Test(dataProvider = "exceptionCases") + @ParameterizedTest + @MethodSource("exceptionCases") public void testException(Class target, boolean useSpec) throws InterruptedException, IOException { runInNewProcess(target, useSpec) .shouldNotHaveExitValue(0) .stderrShouldContain("Testing upcall exceptions"); } - @DataProvider public static Object[][] exceptionCases() { return new Object[][]{ { VoidUpcallRunner.class, false }, diff --git a/test/jdk/java/foreign/TestUpcallHighArity.java b/test/jdk/java/foreign/TestUpcallHighArity.java index 7bb369c884d6..cf448b741a25 100644 --- a/test/jdk/java/foreign/TestUpcallHighArity.java +++ b/test/jdk/java/foreign/TestUpcallHighArity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,13 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * TestUpcallHighArity */ import java.lang.foreign.*; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -44,6 +42,11 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallHighArity extends CallGeneratorHelper { static final MethodHandle MH_do_upcall; @@ -59,7 +62,8 @@ public class TestUpcallHighArity extends CallGeneratorHelper { ); } - @Test(dataProvider = "args") + @ParameterizedTest + @MethodSource("args") public void testUpcall(MethodHandle downcall, MethodType upcallType, FunctionDescriptor upcallDescriptor) throws Throwable { AtomicReference capturedArgs = new AtomicReference<>(); @@ -83,7 +87,6 @@ public void testUpcall(MethodHandle downcall, MethodType upcallType, } } - @DataProvider public static Object[][] args() { return new Object[][]{ { MH_do_upcall, diff --git a/test/jdk/java/foreign/TestUpcallScope.java b/test/jdk/java/foreign/TestUpcallScope.java index 6b8930e1a55d..e7e8c8d9b7be 100644 --- a/test/jdk/java/foreign/TestUpcallScope.java +++ b/test/jdk/java/foreign/TestUpcallScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 * TestUpcallScope */ @@ -35,7 +35,6 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.util.ArrayList; @@ -43,13 +42,19 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallScope extends TestUpcallBase { static { System.loadLibrary("TestUpcall"); } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testUpcalls(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestUpcallStack.java b/test/jdk/java/foreign/TestUpcallStack.java index 4552cbef7349..324489b025d2 100644 --- a/test/jdk/java/foreign/TestUpcallStack.java +++ b/test/jdk/java/foreign/TestUpcallStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * - * @run testng/othervm/native/timeout=480 -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * @run junit/othervm/native/timeout=480 -Xcheck:jni -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 * TestUpcallStack */ @@ -36,7 +36,6 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.util.ArrayList; @@ -44,13 +43,19 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallStack extends TestUpcallBase { static { System.loadLibrary("TestUpcallStack"); } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testUpcallsStack(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestUpcallStress.java b/test/jdk/java/foreign/TestUpcallStress.java index db5320eff372..cc7c83c7f794 100644 --- a/test/jdk/java/foreign/TestUpcallStress.java +++ b/test/jdk/java/foreign/TestUpcallStress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @bug 8337753 * - * @run testng/native/othervm + * @run junit/native/othervm * -Xcheck:jni * -XX:+IgnoreUnrecognizedVMOptions * -XX:-VerifyDependencies @@ -43,9 +43,6 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import jdk.test.lib.Utils; import java.lang.invoke.MethodHandle; @@ -55,6 +52,13 @@ import java.util.concurrent.*; import java.util.function.Consumer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestUpcallStress extends TestUpcallBase { static { @@ -65,12 +69,12 @@ public class TestUpcallStress extends TestUpcallBase { ExecutorService executor; - @BeforeClass + @BeforeAll public void setup() { executor = Executors.newFixedThreadPool(THREAD_COUNT); } - @AfterClass + @AfterAll public void tearDown() throws InterruptedException { executor.shutdown(); // Let it run for a while, and then just terminate @@ -78,7 +82,8 @@ public void tearDown() throws InterruptedException { } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) + @ParameterizedTest + @MethodSource("functions") public void testUpcallsStress(int count, String fName, Ret ret, List paramTypes, List fields) { for (int threadIdx = 0; threadIdx < THREAD_COUNT; threadIdx++) { diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index b71156d9e52f..6a6b35d12f3f 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ /* * @test * - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * TestUpcallStructScope - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * TestUpcallStructScope @@ -37,7 +37,6 @@ import java.lang.foreign.*; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -46,9 +45,10 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; public class TestUpcallStructScope extends NativeTestHelper { static final MethodHandle MH_do_upcall; @@ -117,7 +117,7 @@ public void testOtherPointer() throws Throwable { // We've captured the address '42' from the upcall. This should have // the global scope, so it should still be alive here. MemorySegment captured = capturedSegment.get(); - assertEquals(argAddr, captured); + assertEquals(captured, argAddr); assertTrue(captured.scope().isAlive()); } } diff --git a/test/jdk/java/foreign/TestValueLayouts.java b/test/jdk/java/foreign/TestValueLayouts.java index 4c30a3c7d030..44dcc2a1f76a 100644 --- a/test/jdk/java/foreign/TestValueLayouts.java +++ b/test/jdk/java/foreign/TestValueLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,17 +24,18 @@ /* * @test * @modules java.base/jdk.internal.misc - * @run testng TestValueLayouts + * @run junit TestValueLayouts */ -import org.testng.annotations.*; import java.lang.foreign.*; import java.nio.ByteOrder; import jdk.internal.misc.Unsafe; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestValueLayouts { @@ -141,10 +142,10 @@ void test(ValueLayout layout, Class carrier, long byteSize, long byteAlignment) { - assertEquals(layout.carrier(), carrier); - assertEquals(layout.byteSize(), byteSize); - assertEquals(layout.order(), ByteOrder.nativeOrder()); - assertEquals(layout.byteAlignment(), byteAlignment); + assertEquals(carrier, layout.carrier()); + assertEquals(byteSize, layout.byteSize()); + assertEquals(ByteOrder.nativeOrder(), layout.order()); + assertEquals(byteAlignment, layout.byteAlignment()); assertTrue(layout.name().isEmpty()); } diff --git a/test/jdk/java/foreign/TestVarArgs.java b/test/jdk/java/foreign/TestVarArgs.java index 006105da1a7c..14bc53748987 100644 --- a/test/jdk/java/foreign/TestVarArgs.java +++ b/test/jdk/java/foreign/TestVarArgs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* * @test * @modules java.base/jdk.internal.foreign - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 TestVarArgs + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 TestVarArgs */ import java.lang.foreign.Arena; @@ -35,8 +35,6 @@ import java.lang.foreign.ValueLayout; import java.lang.foreign.MemorySegment; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -48,6 +46,11 @@ import static java.lang.foreign.MemoryLayout.PathElement.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestVarArgs extends CallGeneratorHelper { static final MethodHandle MH_CHECK; @@ -65,7 +68,8 @@ public class TestVarArgs extends CallGeneratorHelper { static final MemorySegment VARARGS_ADDR = findNativeOrThrow("varargs"); - @Test(dataProvider = "variadicFunctions") + @ParameterizedTest + @MethodSource("variadicFunctions") public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff List paramTypes, List fields) throws Throwable { try (Arena arena = Arena.ofConfined()) { @@ -121,7 +125,6 @@ private static List createFieldsForStruct(int fieldCount, Struc return fields; } - @DataProvider(name = "variadicFunctions") public static Object[][] variadicFunctions() { List downcalls = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index ccf12b9fdee7..f7729f499db3 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,20 +24,21 @@ /* * @test - * @run testng TestVarHandleCombinators + * @run junit TestVarHandleCombinators */ import java.lang.foreign.Arena; import java.lang.foreign.ValueLayout; -import org.testng.annotations.Test; import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; public class TestVarHandleCombinators { @@ -47,17 +48,20 @@ public void testElementAccess() { byte[] arr = { 0, 0, -1, 0 }; MemorySegment segment = MemorySegment.ofArray(arr); - assertEquals((byte) vh.get(segment, 2), (byte) -1); + assertEquals((byte) -1, (byte) vh.get(segment, 2)); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testUnalignedElement() { VarHandle vh = ValueLayout.JAVA_BYTE.withByteAlignment(4).varHandle(); MemorySegment segment = MemorySegment.ofArray(new byte[4]); - vh.get(segment, 2L); //should throw + assertThrows(IllegalArgumentException.class, () -> { + vh.get(segment, 2L); + }); //FIXME: the VH only checks the alignment of the segment, which is fine if the VH is derived from layouts, //FIXME: but not if the VH is just created from scratch - we need a VH variable to govern this property, //FIXME: at least until the VM is fixed + } @Test @@ -67,7 +71,7 @@ public void testAlign() { Arena scope = Arena.ofAuto(); MemorySegment segment = scope.allocate(1L, 2); vh.set(segment, 0L, (byte) 10); // fine, memory region is aligned - assertEquals((byte) vh.get(segment, 0L), (byte) 10); + assertEquals((byte) 10, (byte) vh.get(segment, 0L)); } @Test @@ -76,8 +80,8 @@ public void testByteOrderLE() { byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); - assertEquals(arr[0], (byte) 0xFF); - assertEquals(arr[1], (byte) 0); + assertEquals((byte) 0xFF, arr[0]); + assertEquals((byte) 0, arr[1]); } @Test @@ -86,8 +90,8 @@ public void testByteOrderBE() { byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); - assertEquals(arr[0], (byte) 0); - assertEquals(arr[1], (byte) 0xFF); + assertEquals((byte) 0, arr[0]); + assertEquals((byte) 0xFF, arr[1]); } @Test @@ -104,9 +108,7 @@ public void testNestedSequenceAccess() { for (long i = 0; i < outer_size; i++) { for (long j = 0; j < inner_size; j++) { vh.set(segment, i * 40 + j * 8, count); - assertEquals( - (int)vh.get(segment.asSlice(i * inner_size * 8), j * 8), - count); + assertEquals( count, (int)vh.get(segment.asSlice(i * inner_size * 8), j * 8)); count++; } } diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java index 8adf5580f514..bdf163507fe1 100644 --- a/test/jdk/java/foreign/UpcallTestHelper.java +++ b/test/jdk/java/foreign/UpcallTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; public class UpcallTestHelper extends NativeTestHelper { diff --git a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java index 6dba22becdd1..f411bdc5dcce 100644 --- a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java +++ b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @library ../ * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=true @@ -38,15 +38,13 @@ * @library ../ * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=false * -Djdk.internal.foreign.UpcallLinker.USE_SPEC=false * TestArrayStructs */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -64,13 +62,19 @@ import static java.lang.foreign.MemoryLayout.sequenceLayout; import static java.lang.foreign.MemoryLayout.structLayout; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestArrayStructs extends NativeTestHelper { static { System.loadLibrary("ArrayStructs"); } // Test if structs of various different sizes, including non-powers of two, work correctly - @Test(dataProvider = "arrayStructs") + @ParameterizedTest + @MethodSource("arrayStructs") public void testArrayStruct(String functionName, FunctionDescriptor baseDesc, int numPrefixArgs, int numElements) throws Throwable { FunctionDescriptor downcallDesc = baseDesc.insertArgumentLayouts(0, C_POINTER); // CB MemoryLayout[] elementLayouts = Collections.nCopies(numElements, C_CHAR).toArray(MemoryLayout[]::new); @@ -109,7 +113,6 @@ public void testArrayStruct(String functionName, FunctionDescriptor baseDesc, in } } - @DataProvider public static Object[][] arrayStructs() { List cases = new ArrayList<>(); for (int i = 0; i < layouts.size(); i++) { diff --git a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java index 037db225c65f..d37ebd32377f 100644 --- a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java +++ b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,22 +27,22 @@ import java.util.Arrays; import java.util.List; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class CallArrangerTestBase { public static void checkArgumentBindings(CallingSequence callingSequence, Binding[][] argumentBindings) { - assertEquals(callingSequence.argumentBindingsCount(), argumentBindings.length, + assertEquals(argumentBindings.length, callingSequence.argumentBindingsCount(), callingSequence.asString() + " != " + Arrays.deepToString(argumentBindings)); for (int i = 0; i < callingSequence.argumentBindingsCount(); i++) { List actual = callingSequence.argumentBindings(i); Binding[] expected = argumentBindings[i]; - assertEquals(actual, Arrays.asList(expected), "bindings at: " + i + ": " + actual + " != " + Arrays.toString(expected)); + assertEquals(Arrays.asList(expected), actual, "bindings at: " + i + ": " + actual + " != " + Arrays.toString(expected)); } } public static void checkReturnBindings(CallingSequence callingSequence, Binding[] returnBindings) { - assertEquals(callingSequence.returnBindings(), Arrays.asList(returnBindings), callingSequence.returnBindings() + " != " + Arrays.toString(returnBindings)); + assertEquals(Arrays.asList(returnBindings), callingSequence.returnBindings(), callingSequence.returnBindings() + " != " + Arrays.toString(returnBindings)); } } diff --git a/test/jdk/java/foreign/callarranger/TestLayoutEquality.java b/test/jdk/java/foreign/callarranger/TestLayoutEquality.java index 0f4314894963..96ee11f6a96e 100644 --- a/test/jdk/java/foreign/callarranger/TestLayoutEquality.java +++ b/test/jdk/java/foreign/callarranger/TestLayoutEquality.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign.abi * @modules java.base/jdk.internal.foreign.layout - * @run testng TestLayoutEquality + * @run junit TestLayoutEquality */ import java.lang.foreign.AddressLayout; @@ -35,18 +35,21 @@ import jdk.internal.foreign.layout.ValueLayouts; import platform.PlatformLayouts; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestLayoutEquality { - @Test(dataProvider = "layoutConstants") + @ParameterizedTest + @MethodSource("layoutConstants") public void testReconstructedEquality(ValueLayout layout) { ValueLayout newLayout = ValueLayouts.valueLayout(layout.carrier(), layout.order()); newLayout = newLayout.withByteAlignment(layout.byteAlignment()); @@ -55,15 +58,14 @@ public void testReconstructedEquality(ValueLayout layout) { } // properties should be equal - assertEquals(newLayout.byteSize(), layout.byteSize()); - assertEquals(newLayout.byteAlignment(), layout.byteAlignment()); - assertEquals(newLayout.name(), layout.name()); + assertEquals(layout.byteSize(), newLayout.byteSize()); + assertEquals(layout.byteAlignment(), newLayout.byteAlignment()); + assertEquals(layout.name(), newLayout.name()); // layouts should be equals - assertEquals(newLayout, layout); + assertEquals(layout, newLayout); } - @DataProvider public static Object[][] layoutConstants() throws ReflectiveOperationException { List testValues = new ArrayList<>(); diff --git a/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java index ae08f1c9be43..ca0e25eedf24 100644 --- a/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * java.base/jdk.internal.foreign.abi * java.base/jdk.internal.foreign.abi.aarch64 * @build CallArrangerTestBase - * @run testng TestLinuxAArch64CallArranger + * @run junit TestLinuxAArch64CallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -43,8 +43,6 @@ import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.aarch64.CallArranger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodType; @@ -55,10 +53,15 @@ import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; import static platform.PlatformLayouts.AArch64.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestLinuxAArch64CallArranger extends CallArrangerTestBase { private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); @@ -72,8 +75,8 @@ public void testEmpty() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } @@ -96,8 +99,8 @@ public void testInteger() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -126,8 +129,8 @@ public void testTwoIntTwoFloat() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -140,7 +143,8 @@ public void testTwoIntTwoFloat() { checkReturnBindings(callingSequence, new Binding[]{}); } - @Test(dataProvider = "structs") + @ParameterizedTest + @MethodSource("structs") public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); @@ -148,8 +152,8 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -159,7 +163,6 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { checkReturnBindings(callingSequence, new Binding[]{}); } - @DataProvider public static Object[][] structs() { MemoryLayout struct2 = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE, C_INT); return new Object[][]{ @@ -208,8 +211,8 @@ public void testMultipleStructs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -239,8 +242,8 @@ public void testReturnStruct1() { assertTrue(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); + assertEquals(MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(FunctionDescriptor.ofVoid(ADDRESS, C_POINTER), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -263,8 +266,8 @@ public void testReturnStruct2() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, @@ -292,8 +295,8 @@ public void testStructHFA1() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, @@ -330,8 +333,8 @@ public void testStructHFA3() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -384,8 +387,8 @@ public void testStructStackSpill() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -413,8 +416,8 @@ public void testVarArgsInRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ @@ -440,8 +443,8 @@ public void testFloatArrayStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ diff --git a/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java index 30119db72e8c..b8217f913399 100644 --- a/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * java.base/jdk.internal.foreign.abi * java.base/jdk.internal.foreign.abi.aarch64 * @build CallArrangerTestBase - * @run testng TestMacOsAArch64CallArranger + * @run junit TestMacOsAArch64CallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -43,8 +43,6 @@ import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.aarch64.CallArranger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodType; @@ -54,9 +52,11 @@ import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; import static platform.PlatformLayouts.AArch64.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; public class TestMacOsAArch64CallArranger extends CallArrangerTestBase { @@ -71,8 +71,8 @@ public void testVarArgsOnStack() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); // The two variadic arguments should be allocated on the stack checkArgumentBindings(callingSequence, new Binding[][]{ @@ -99,8 +99,8 @@ public void testMacArgsOnStack() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -143,8 +143,8 @@ public void testMacArgsOnStack2() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -199,8 +199,8 @@ public void testMacArgsOnStack3() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -252,8 +252,8 @@ public void testMacArgsOnStack4() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -304,8 +304,8 @@ public void testMacArgsOnStack5() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -358,8 +358,8 @@ public void testMacArgsOnStack6() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, diff --git a/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java b/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java index f24862396459..7bd673aff278 100644 --- a/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Institute of Software, Chinese Academy of Sciences. * All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -33,7 +33,7 @@ * java.base/jdk.internal.foreign.abi.riscv64 * java.base/jdk.internal.foreign.abi.riscv64.linux * @build CallArrangerTestBase - * @run testng TestRISCV64CallArranger + * @run junit TestRISCV64CallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -45,8 +45,6 @@ import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64CallArranger; import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodType; @@ -58,10 +56,15 @@ import static jdk.internal.foreign.abi.riscv64.RISCV64Architecture.Regs.*; import static platform.PlatformLayouts.RISCV64.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestRISCV64CallArranger extends CallArrangerTestBase { private static final short STACK_SLOT_SIZE = 8; @@ -76,8 +79,8 @@ public void testEmpty() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } @@ -100,8 +103,8 @@ public void testInteger() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -128,8 +131,8 @@ public void testTwoIntTwoFloat() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -142,7 +145,8 @@ public void testTwoIntTwoFloat() { checkReturnBindings(callingSequence, new Binding[]{}); } - @Test(dataProvider = "structs") + @ParameterizedTest + @MethodSource("structs") public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); @@ -150,8 +154,8 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -161,7 +165,6 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { checkReturnBindings(callingSequence, new Binding[]{}); } - @DataProvider public static Object[][] structs() { MemoryLayout struct1 = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE, C_INT); return new Object[][]{ @@ -226,8 +229,8 @@ public void testStructFA1() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, @@ -264,8 +267,8 @@ public void testStructFA2() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, @@ -305,8 +308,8 @@ void spillFloatingPointStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -336,8 +339,8 @@ public void testStructBoth() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -384,8 +387,8 @@ public void testStructStackSpill() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -413,8 +416,8 @@ public void testVarArgsInRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ @@ -442,8 +445,8 @@ public void testVarArgsLong() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ @@ -474,11 +477,9 @@ public void testReturnStruct1() { assertTrue(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), - MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, - int.class, int.class, float.class)); - assertEquals(callingSequence.functionDesc(), - FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_INT, C_INT, C_FLOAT)); + assertEquals( MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, + int.class, int.class, float.class), callingSequence.callerMethodType()); + assertEquals( FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_INT, C_INT, C_FLOAT), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -501,8 +502,8 @@ public void testReturnStruct2() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index 53317b22dc08..8f911242d22f 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * java.base/jdk.internal.foreign.abi.x64 * java.base/jdk.internal.foreign.abi.x64.sysv * @build CallArrangerTestBase - * @run testng TestSysVCallArranger + * @run junit TestSysVCallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -41,8 +41,6 @@ import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.x64.sysv.CallArranger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodType; @@ -52,10 +50,15 @@ import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; import static platform.PlatformLayouts.SysV.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSysVCallArranger extends CallArrangerTestBase { private static final short STACK_SLOT_SIZE = 8; @@ -70,8 +73,8 @@ public void testEmpty() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -79,7 +82,7 @@ public void testEmpty() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -97,8 +100,8 @@ public void testNestedStructs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -108,7 +111,7 @@ public void testNestedStructs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -127,8 +130,8 @@ public void testNestedUnion() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -138,7 +141,7 @@ public void testNestedUnion() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -151,8 +154,8 @@ public void testIntegerRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -166,7 +169,7 @@ public void testIntegerRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -181,8 +184,8 @@ public void testDoubleRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -198,7 +201,7 @@ public void testDoubleRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 8); + assertEquals(8, bindings.nVectorArgs()); } @Test @@ -215,8 +218,8 @@ public void testMixed() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -242,7 +245,7 @@ public void testMixed() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 8); + assertEquals(8, bindings.nVectorArgs()); } /** @@ -271,8 +274,8 @@ public void testAbiExample() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -294,7 +297,7 @@ public void testAbiExample() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 3); + assertEquals(3, bindings.nVectorArgs()); } /** @@ -313,8 +316,8 @@ public void testMemoryAddress() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -323,10 +326,11 @@ public void testMemoryAddress() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } - @Test(dataProvider = "structs") + @ParameterizedTest + @MethodSource("structs") public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); @@ -334,8 +338,8 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -344,11 +348,10 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } - @DataProvider public static Object[][] structs() { return new Object[][]{ { MemoryLayout.structLayout(C_LONG), new Binding[]{ @@ -392,8 +395,8 @@ public void testReturnRegisterStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, @@ -410,7 +413,7 @@ public void testReturnRegisterStruct() { bufferStore(8, long.class) }); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -423,8 +426,8 @@ public void testIMR() { assertTrue(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); + assertEquals(MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(FunctionDescriptor.ofVoid(ADDRESS, C_POINTER), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -433,7 +436,7 @@ public void testIMR() { checkReturnBindings(callingSequence, new Binding[] {}); - assertEquals(bindings.nVectorArgs(), 0); + assertEquals(0, bindings.nVectorArgs()); } @Test @@ -446,8 +449,8 @@ public void testFloatStructsUpcall() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.calleeMethodType(), mt); - assertEquals(callingSequence.functionDesc(), fd); + assertEquals(mt, callingSequence.calleeMethodType()); + assertEquals(fd, callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { allocate(struct), dup(), vmLoad(xmm0, float.class), bufferStore(0, float.class) }, @@ -457,7 +460,7 @@ public void testFloatStructsUpcall() { bufferLoad(0, float.class), vmStore(xmm0, float.class) }); - assertEquals(bindings.nVectorArgs(), 1); + assertEquals(1, bindings.nVectorArgs()); } } diff --git a/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java index 4c612ef868c6..c799e90d6ccc 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * java.base/jdk.internal.foreign.abi * java.base/jdk.internal.foreign.abi.aarch64 * @build CallArrangerTestBase - * @run testng TestWindowsAArch64CallArranger + * @run junit TestWindowsAArch64CallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -41,8 +41,6 @@ import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.aarch64.CallArranger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodType; @@ -52,9 +50,11 @@ import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; import static platform.PlatformLayouts.AArch64.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; public class TestWindowsAArch64CallArranger extends CallArrangerTestBase { @@ -69,8 +69,8 @@ public void testWindowsArgsInRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -92,8 +92,8 @@ public void testWindowsVarArgsInRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -118,8 +118,8 @@ public void testWindowsArgsInRegsAndOnStack() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -152,8 +152,8 @@ public void testWindowsVarArgsInRegsAndOnStack() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -182,8 +182,8 @@ public void testWindowsHfa4FloatsInFloatRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -216,8 +216,8 @@ public void testWindowsVariadicHfa4FloatsInIntRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -245,8 +245,8 @@ public void testWindowsHfa2DoublesInFloatRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -274,8 +274,8 @@ public void testWindowsVariadicHfa2DoublesInIntRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -303,8 +303,8 @@ public void testWindowsHfa3DoublesInFloatRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -335,8 +335,8 @@ public void testWindowsVariadicHfa3DoublesAsReferenceStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index 3f47952dd83e..25fc025f047e 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * java.base/jdk.internal.foreign.abi.x64 * java.base/jdk.internal.foreign.abi.x64.windows * @build CallArrangerTestBase - * @run testng TestWindowsCallArranger + * @run junit TestWindowsCallArranger */ import java.lang.foreign.FunctionDescriptor; @@ -43,7 +43,6 @@ import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.x64.windows.CallArranger; -import org.testng.annotations.Test; import java.lang.invoke.MethodType; @@ -55,7 +54,8 @@ import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; import static platform.PlatformLayouts.Win64.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TestWindowsCallArranger extends CallArrangerTestBase { @@ -70,8 +70,8 @@ public void testEmpty() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } @@ -87,8 +87,8 @@ public void testIntegerRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -109,8 +109,8 @@ public void testDoubleRegs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -133,8 +133,8 @@ public void testMixed() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -164,8 +164,8 @@ public void testAbiExample() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -201,8 +201,8 @@ public void testAbiExampleVarargs() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fdExpected); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fdExpected, callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -235,8 +235,8 @@ public void testStructRegister() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -265,8 +265,8 @@ public void testStructReference() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -296,8 +296,8 @@ public void testMemoryAddress() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -317,8 +317,8 @@ public void testReturnRegisterStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -341,8 +341,8 @@ public void testIMR() { assertTrue(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); + assertEquals(MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(FunctionDescriptor.ofVoid(ADDRESS, C_POINTER), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, @@ -370,8 +370,8 @@ public void testStackStruct() { assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); - assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + assertEquals(mt.insertParameterTypes(0, MemorySegment.class), callingSequence.callerMethodType()); + assertEquals(fd.insertArgumentLayouts(0, ADDRESS), callingSequence.functionDesc()); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, diff --git a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java index 8ef5483bd82a..f88dd051841c 100644 --- a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java +++ b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java @@ -25,11 +25,9 @@ * @test * @bug 8356126 * @library ../ /test/lib - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestCaptureCallState + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestCaptureCallState */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -48,8 +46,14 @@ import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_LONG; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestCaptureCallState extends NativeTestHelper { static { @@ -67,7 +71,7 @@ public void testApiContracts() { assertThrows(IllegalArgumentException.class, () -> Linker.Option.captureCallState("Does not exist")); var duplicateOpt = Linker.Option.captureCallState("errno", "errno"); // duplicates var noDuplicateOpt = Linker.Option.captureCallState("errno"); - assertEquals(duplicateOpt, noDuplicateOpt, "auto deduplication"); + assertEquals(noDuplicateOpt, duplicateOpt, "auto deduplication"); var display = duplicateOpt.toString(); assertTrue(display.contains("errno"), "toString should contain state name 'errno': " + display); } @@ -75,7 +79,8 @@ public void testApiContracts() { private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, Consumer resultCheck, boolean expectTestValue, boolean critical) {} - @Test(dataProvider = "cases") + @ParameterizedTest + @MethodSource("cases") public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { List options = new ArrayList<>(); options.add(Linker.Option.captureCallState(testCase.threadLocalName())); @@ -101,14 +106,15 @@ public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { testCase.resultCheck().accept(result); int savedErrno = (int) errnoHandle.get(saveSeg, 0L); if (testCase.expectTestValue()) { - assertEquals(savedErrno, testValue); + assertEquals(testValue, savedErrno); } else { - assertEquals(savedErrno, prevValue); + assertEquals(prevValue, savedErrno); } } } - @Test(dataProvider = "invalidCaptureSegmentCases") + @ParameterizedTest + @MethodSource("invalidCaptureSegmentCases") public void testInvalidCaptureSegment(MemorySegment captureSegment, Class expectedExceptionType, String expectedExceptionMessage, Linker.Option[] extraOptions) { @@ -128,7 +134,6 @@ public void testInvalidCaptureSegment(MemorySegment captureSegment, } } - @DataProvider public static Object[][] cases() { List cases = new ArrayList<>(); @@ -138,9 +143,9 @@ public static Object[][] cases() { cases.add(new SaveValuesCase("noset_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), "errno", o -> {}, false, critical)); cases.add(new SaveValuesCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), - "errno", o -> assertEquals((int) o, 42), true, critical)); + "errno", o -> assertEquals(42, (int) o), true, critical)); cases.add(new SaveValuesCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), - "errno", o -> assertEquals((double) o, 42.0), true, critical)); + "errno", o -> assertEquals(42.0, (double) o), true, critical)); cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L), true, critical)); cases.add(structCase("SLL", Map.of(JAVA_LONG.withName("x"), 42L, @@ -180,14 +185,13 @@ static SaveValuesCase structCase(String name, MemoryLayout fieldLayout = field.getKey(); VarHandle fieldHandle = layout.varHandle(MemoryLayout.PathElement.groupElement(fieldLayout.name().get())); Object value = field.getValue(); - check = check.andThen(o -> assertEquals(fieldHandle.get(o, 0L), value)); + check = check.andThen(o -> assertEquals(value, fieldHandle.get(o, 0L))); } String prefix = expectTestValue ? "set_errno_" : "noset_errno_"; return new SaveValuesCase(prefix + name, FunctionDescriptor.of(layout, JAVA_INT), "errno", check, expectTestValue, critical); } - @DataProvider public static Object[][] invalidCaptureSegmentCases() { return new Object[][]{ {Arena.ofAuto().allocate(1), IndexOutOfBoundsException.class, ".*Out of bound access on segment.*", new Linker.Option[0]}, diff --git a/test/jdk/java/foreign/channels/AbstractChannelsTest.java b/test/jdk/java/foreign/channels/AbstractChannelsTest.java index 6c9e64a40a27..b22342cb067f 100644 --- a/test/jdk/java/foreign/channels/AbstractChannelsTest.java +++ b/test/jdk/java/foreign/channels/AbstractChannelsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,14 +32,16 @@ import java.util.stream.Stream; import jdk.test.lib.RandomFactory; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; /** * Not a test, but infra for channel tests. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class AbstractChannelsTest { static final Class IOE = IOException.class; @@ -120,28 +122,24 @@ static void assertCauses(Throwable ex, Class... exceptions) } } - @DataProvider(name = "confinedArenas") public static Object[][] confinedArenas() { return new Object[][] { { ArenaSupplier.NEW_CONFINED }, }; } - @DataProvider(name = "sharedArenas") public static Object[][] sharedArenas() { return new Object[][] { { ArenaSupplier.NEW_SHARED }, }; } - @DataProvider(name = "closeableArenas") public static Object[][] closeableArenas() { return Stream.of(sharedArenas(), confinedArenas()) .flatMap(Arrays::stream) .toArray(Object[][]::new); } - @DataProvider(name = "sharedArenasAndTimeouts") public static Object[][] sharedArenasAndTimeouts() { return new Object[][] { { ArenaSupplier.NEW_SHARED , 0 }, diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 37fef8bb4b66..9f315f10d75f 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,9 @@ * @library /test/lib * @modules java.base/sun.nio.ch * @key randomness - * @run testng/othervm TestAsyncSocketChannels - * @run testng/othervm -Dsun.nio.ch.disableSynchronousRead=true TestAsyncSocketChannels - * @run testng/othervm -Dsun.nio.ch.disableSynchronousRead=false TestAsyncSocketChannels + * @run junit/othervm TestAsyncSocketChannels + * @run junit/othervm -Dsun.nio.ch.disableSynchronousRead=true TestAsyncSocketChannels + * @run junit/othervm -Dsun.nio.ch.disableSynchronousRead=false TestAsyncSocketChannels */ import java.io.IOException; @@ -50,15 +50,19 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; -import org.testng.annotations.*; import static java.lang.System.out; import static java.util.concurrent.TimeUnit.SECONDS; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests consisting of buffer views with asynchronous NIO network channels. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestAsyncSocketChannels extends AbstractChannelsTest { static final Class IOE = IOException.class; @@ -67,7 +71,8 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; /** Tests that confined sessions are not supported. */ - @Test(dataProvider = "confinedArenas") + @ParameterizedTest + @MethodSource("confinedArenas") public void testWithConfined(Supplier arenaSupplier) throws Throwable { @@ -92,13 +97,14 @@ public void testWithConfined(Supplier arenaSupplier) for (var ioOp : ioOps) { out.println("testAsyncWithConfined - op"); var handler = new TestHandler(); - expectThrows(IAE, () -> ioOp.accept(handler)); + assertThrows(IAE, () -> ioOp.accept(handler)); } } } /** Tests that I/O with a closed session throws a suitable exception. */ - @Test(dataProvider = "sharedArenasAndTimeouts") + @ParameterizedTest + @MethodSource("sharedArenasAndTimeouts") public void testIOWithClosedSharedSession(Supplier arenaSupplier, int timeout) throws Exception { @@ -110,7 +116,7 @@ public void testIOWithClosedSharedSession(Supplier arenaSupplier, int tim ByteBuffer[] buffers = segmentBuffersOfSize(8, drop, 32); drop.close(); { - assertCauses(expectThrows(EE, () -> connectedChannel.read(bb).get()), IOE, ISE); + assertCauses(assertThrows(EE, () -> connectedChannel.read(bb).get()), IOE, ISE); } { var handler = new TestHandler(); @@ -128,7 +134,7 @@ public void testIOWithClosedSharedSession(Supplier arenaSupplier, int tim handler.await().assertFailedWith(ISE).assertExceptionMessage("Already closed"); } { - assertCauses(expectThrows(EE, () -> connectedChannel.write(bb).get()), IOE, ISE); + assertCauses(assertThrows(EE, () -> connectedChannel.write(bb).get()), IOE, ISE); } { var handler = new TestHandler(); @@ -149,7 +155,8 @@ public void testIOWithClosedSharedSession(Supplier arenaSupplier, int tim } /** Tests basic I/O operations work with views over implicit and shared sessions. */ - @Test(dataProvider = "sharedArenas") + @ParameterizedTest + @MethodSource("sharedArenas") public void testBasicIOWithSupportedSession(Supplier arenaSupplier) throws Exception { @@ -168,9 +175,9 @@ public void testBasicIOWithSupportedSession(Supplier arenaSupplier) { // Future variants ByteBuffer bb1 = segment1.asByteBuffer(); ByteBuffer bb2 = segment2.asByteBuffer(); - assertEquals((int)asc1.write(bb1).get(), 10); - assertEquals((int)asc2.read(bb2).get(), 10); - assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + assertEquals(10, (int)asc1.write(bb1).get()); + assertEquals(10, (int)asc2.read(bb2).get()); + assertEquals(ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), bb2.flip()); } { // CompletionHandler variants ByteBuffer bb1 = segment1.asByteBuffer(); @@ -181,7 +188,7 @@ public void testBasicIOWithSupportedSession(Supplier arenaSupplier) var readHandler = new TestHandler(); asc2.read(new ByteBuffer[]{bb2}, 0, 1, 30L, SECONDS, null, readHandler); readHandler.await().assertCompleteWith(10L); - assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + assertEquals(ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), bb2.flip()); } { // Gathering/Scattering variants var writeBuffers = mixedBuffersOfSize(16, drop, 32); @@ -193,13 +200,14 @@ public void testBasicIOWithSupportedSession(Supplier arenaSupplier) var readHandler = new TestHandler(); asc2.read(readBuffers, 0, 16, 30L, SECONDS, null, readHandler); readHandler.await().assertCompleteWith(expectedCount); - assertEquals(flip(readBuffers), clear(writeBuffers)); + assertArrayEquals(clear(writeBuffers), flip(readBuffers)); } } } /** Tests that a session is not closeable when there is an outstanding read operation. */ - @Test(dataProvider = "sharedArenasAndTimeouts") + @ParameterizedTest + @MethodSource("sharedArenasAndTimeouts") public void testCloseWithOutstandingRead(Supplier arenaSupplier, int timeout) throws Throwable { @@ -235,7 +243,8 @@ public void testCloseWithOutstandingRead(Supplier arenaSupplier, int time /** Tests that a session is not closeable when there is an outstanding write operation. */ // Note: limited scenarios are checked, given the 5 sec sleep! - @Test(dataProvider = "sharedArenasAndTimeouts") + @ParameterizedTest + @MethodSource("sharedArenasAndTimeouts") public void testCloseWithOutstandingWrite(Supplier arenaSupplier, int timeout) throws Throwable { @@ -357,20 +366,20 @@ TestHandler await() throws InterruptedException{ } TestHandler assertCompleteWith(V value) { - assertEquals(result.longValue(), value.longValue()); - assertEquals(throwable, null); + assertEquals(value.longValue(), result.longValue()); + assertEquals(null, throwable); return this; } TestHandler assertFailedWith(Class expectedException) { assertTrue(expectedException.isInstance(throwable), "Expected type:%s, got:%s".formatted(expectedException, throwable) ); - assertEquals(result, null, "Unexpected result: " + result); + assertEquals(null, result, "Unexpected result: " + result); return this; } TestHandler assertExceptionMessage(String expectedMessage) { - assertEquals(throwable.getMessage(), expectedMessage); + assertEquals(expectedMessage, throwable.getMessage()); return this; } diff --git a/test/jdk/java/foreign/channels/TestSocketChannels.java b/test/jdk/java/foreign/channels/TestSocketChannels.java index e2cb012a5088..77bc79c34084 100644 --- a/test/jdk/java/foreign/channels/TestSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestSocketChannels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @library /test/lib * @modules java.base/sun.nio.ch * @key randomness - * @run testng/othervm TestSocketChannels + * @run junit/othervm TestSocketChannels */ import java.lang.foreign.Arena; @@ -43,20 +43,27 @@ import java.lang.foreign.MemorySegment; -import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests consisting of buffer views with synchronous NIO network channels. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; static final Class WTE = WrongThreadException.class; - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testBasicIOWithClosedSegment(Supplier arenaSupplier) throws Exception { @@ -66,16 +73,17 @@ public void testBasicIOWithClosedSegment(Supplier arenaSupplier) Arena drop = arenaSupplier.get(); ByteBuffer bb = segmentBufferOfSize(drop, 16); drop.close(); - assertMessage(expectThrows(ISE, () -> channel.read(bb)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.write(bb)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.write(new ByteBuffer[] {bb})), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.read(bb)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.write(bb)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb})), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1)), "Already closed"); } } - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testScatterGatherWithClosedSegment(Supplier arenaSupplier) throws Exception { @@ -85,14 +93,15 @@ public void testScatterGatherWithClosedSegment(Supplier arenaSupplier) Arena drop = arenaSupplier.get(); ByteBuffer[] buffers = segmentBuffersOfSize(8, drop, 16); drop.close(); - assertMessage(expectThrows(ISE, () -> channel.write(buffers)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.read(buffers)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.write(buffers, 0 ,8)), "Already closed"); - assertMessage(expectThrows(ISE, () -> channel.read(buffers, 0, 8)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.write(buffers)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.read(buffers)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.write(buffers, 0 ,8)), "Already closed"); + assertMessage(assertThrows(ISE, () -> channel.read(buffers, 0, 8)), "Already closed"); } } - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testBasicIO(Supplier arenaSupplier) throws Exception { @@ -110,9 +119,9 @@ public void testBasicIO(Supplier arenaSupplier) } ByteBuffer bb1 = segment1.asByteBuffer(); ByteBuffer bb2 = segment2.asByteBuffer(); - assertEquals(sc1.write(bb1), 10); - assertEquals(sc2.read(bb2), 10); - assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + assertEquals(10, sc1.write(bb1)); + assertEquals(10, sc2.read(bb2)); + assertEquals(ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), bb2.flip()); } } @@ -128,13 +137,14 @@ public void testBasicHeapIOWithGlobalSession() throws Exception { } ByteBuffer bb1 = segment1.asByteBuffer(); ByteBuffer bb2 = segment2.asByteBuffer(); - assertEquals(sc1.write(bb1), 10); - assertEquals(sc2.read(bb2), 10); - assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + assertEquals(10, sc1.write(bb1)); + assertEquals(10, sc2.read(bb2)); + assertEquals(ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), bb2.flip()); } } - @Test(dataProvider = "confinedArenas") + @ParameterizedTest + @MethodSource("confinedArenas") public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) throws Exception { @@ -145,7 +155,7 @@ public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) Arena scope = drop; var segment = scope.allocate(10, 1); ByteBuffer bb = segment.asByteBuffer(); - List ioOps = List.of( + List ioOps = List.of( () -> channel.write(bb), () -> channel.read(bb), () -> channel.write(new ByteBuffer[] {bb}), @@ -155,7 +165,7 @@ public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) ); for (var ioOp : ioOps) { AtomicReference exception = new AtomicReference<>(); - Runnable task = () -> exception.set(expectThrows(WTE, ioOp)); + Runnable task = () -> exception.set(assertThrows(WTE, ioOp)); var t = new Thread(task); t.start(); t.join(); @@ -164,7 +174,8 @@ public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) } } - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testScatterGatherIO(Supplier arenaSupplier) throws Exception { @@ -176,13 +187,14 @@ public void testScatterGatherIO(Supplier arenaSupplier) var writeBuffers = mixedBuffersOfSize(32, drop, 64); var readBuffers = mixedBuffersOfSize(32, drop, 64); long expectedCount = remaining(writeBuffers); - assertEquals(writeNBytes(sc1, writeBuffers, 0, 32, expectedCount), expectedCount); - assertEquals(readNBytes(sc2, readBuffers, 0, 32, expectedCount), expectedCount); - assertEquals(flip(readBuffers), clear(writeBuffers)); + assertEquals(expectedCount, writeNBytes(sc1, writeBuffers, 0, 32, expectedCount)); + assertEquals(expectedCount, readNBytes(sc2, readBuffers, 0, 32, expectedCount)); + assertArrayEquals(clear(writeBuffers), flip(readBuffers)); } } - @Test(dataProvider = "closeableArenas") + @ParameterizedTest + @MethodSource("closeableArenas") public void testBasicIOWithDifferentSessions(Supplier arenaSupplier) throws Exception { @@ -199,9 +211,9 @@ public void testBasicIOWithDifferentSessions(Supplier arenaSupplier) .toArray(ByteBuffer[]::new); long expectedCount = remaining(writeBuffers); - assertEquals(writeNBytes(sc1, writeBuffers, 0, 32, expectedCount), expectedCount); - assertEquals(readNBytes(sc2, readBuffers, 0, 32, expectedCount), expectedCount); - assertEquals(flip(readBuffers), clear(writeBuffers)); + assertEquals(expectedCount, writeNBytes(sc1, writeBuffers, 0, 32, expectedCount)); + assertEquals(expectedCount, readNBytes(sc2, readBuffers, 0, 32, expectedCount)); + assertArrayEquals(clear(writeBuffers), flip(readBuffers)); } } diff --git a/test/jdk/java/foreign/critical/TestCritical.java b/test/jdk/java/foreign/critical/TestCritical.java index 499278685cf6..4c09b302058f 100644 --- a/test/jdk/java/foreign/critical/TestCritical.java +++ b/test/jdk/java/foreign/critical/TestCritical.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ * @test * @library ../ /test/lib * - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestCritical + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestCritical */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -48,8 +46,13 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestCritical extends NativeTestHelper { static final MemoryLayout CAPTURE_STATE_LAYOUT = Linker.Option.captureStateLayout(); @@ -69,7 +72,7 @@ public void testEmpty() throws Throwable { public void testIdentity() throws Throwable { MethodHandle handle = downcallHandle("identity", FunctionDescriptor.of(C_INT, C_INT), Linker.Option.critical(false)); int result = (int) handle.invokeExact(42); - assertEquals(result, 42); + assertEquals(42, result); } @Test @@ -84,16 +87,17 @@ public void testWithReturnBuffer() throws Throwable { try (Arena arena = Arena.ofConfined()) { MemorySegment result = (MemorySegment) handle.invokeExact((SegmentAllocator) arena); long x = (long) vhX.get(result, 0L); - assertEquals(x, 10); + assertEquals(10, x); long y = (long) vhY.get(result, 0L); - assertEquals(y, 11); + assertEquals(11, y); } } public record AllowHeapCase(IntFunction newArraySegment, ValueLayout elementLayout, String fName, FunctionDescriptor fDesc, boolean readOnly, boolean captureErrno) {} - @Test(dataProvider = "allowHeapCases") + @ParameterizedTest + @MethodSource("allowHeapCases") public void testAllowHeap(AllowHeapCase testCase) throws Throwable { List options = new ArrayList<>(); options.add(Linker.Option.critical(true)); @@ -138,12 +142,11 @@ public void testAllowHeap(AllowHeapCase testCase) throws Throwable { if (testCase.captureErrno()) { int errno = (int) ERRNO_HANDLE.get(captureSegment, 0L); - assertEquals(errno, 42); + assertEquals(42, errno); } } } - @DataProvider public Object[][] allowHeapCases() { FunctionDescriptor voidDesc = FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_INT); FunctionDescriptor intDesc = voidDesc.changeReturnLayout(C_INT).insertArgumentLayouts(0, C_INT); diff --git a/test/jdk/java/foreign/critical/TestCriticalUpcall.java b/test/jdk/java/foreign/critical/TestCriticalUpcall.java index d6fd640539e7..c4f59bc5ac10 100644 --- a/test/jdk/java/foreign/critical/TestCriticalUpcall.java +++ b/test/jdk/java/foreign/critical/TestCriticalUpcall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,9 @@ * @test * @library ../ /test/lib * @requires jdk.foreign.linker != "FALLBACK" - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestCriticalUpcall + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestCriticalUpcall */ -import org.testng.annotations.Test; import java.io.IOException; import java.lang.foreign.FunctionDescriptor; @@ -37,7 +36,8 @@ import java.lang.invoke.MethodHandle; import java.util.List; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; public class TestCriticalUpcall extends UpcallTestHelper { diff --git a/test/jdk/java/foreign/dontrelease/TestDontRelease.java b/test/jdk/java/foreign/dontrelease/TestDontRelease.java index b107c758ba2c..f3f67370b775 100644 --- a/test/jdk/java/foreign/dontrelease/TestDontRelease.java +++ b/test/jdk/java/foreign/dontrelease/TestDontRelease.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,10 @@ * @test * @library ../ /test/lib * @modules java.base/jdk.internal.ref java.base/jdk.internal.foreign - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestDontRelease + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestDontRelease */ import jdk.internal.foreign.MemorySessionImpl; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -38,7 +37,9 @@ import static java.lang.foreign.ValueLayout.ADDRESS; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; public class TestDontRelease extends NativeTestHelper { diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java index 6fc3f79260bf..43d6e747935b 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java @@ -33,7 +33,7 @@ * panama_jni_use_module/* * * org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule - * @run testng/othervm/native/timeout=180 TestEnableNativeAccess + * @run junit/othervm/native/timeout=180 TestEnableNativeAccess * @summary Basic test for java --enable-native-access */ @@ -43,9 +43,11 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Basic test of --enable-native-access with expected behaviour: @@ -57,10 +59,9 @@ * (on first access per module only) */ -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestEnableNativeAccess extends TestEnableNativeAccessBase { - @DataProvider(name = "succeedCases") public Object[][] succeedCases() { return new Object[][] { { "panama_enable_native_access", PANAMA_MAIN, successNoWarning(), new String[]{"--enable-native-access=panama_module"} }, @@ -110,7 +111,8 @@ OutputAnalyzer run(String action, String cls, Result expectedResult, String... v return outputAnalyzer; } - @Test(dataProvider = "succeedCases") + @ParameterizedTest + @MethodSource("succeedCases") public void testSucceed(String action, String cls, Result expectedResult, String... vmopts) throws Exception { run(action, cls, expectedResult, vmopts); } @@ -119,6 +121,7 @@ public void testSucceed(String action, String cls, Result expectedResult, String * Tests that without --enable-native-access, a multi-line warning is printed * on first access of a module. */ + @Test public void testWarnFirstAccess() throws Exception { List output1 = run("panama_enable_native_access_first", PANAMA_MAIN, successWithWarning("panama")).asLines(); @@ -129,6 +132,7 @@ public void testWarnFirstAccess() throws Exception { * Specifies --enable-native-access more than once, each list of module names * is appended. */ + @Test public void testRepeatedOption() throws Exception { run("panama_enable_native_access_last_one_wins", PANAMA_MAIN, success(), "--enable-native-access=java.base", "--enable-native-access=panama_module"); @@ -139,6 +143,7 @@ public void testRepeatedOption() throws Exception { /** * Specifies bad value to --enable-native-access. */ + @Test public void testBadValue() throws Exception { run("panama_deny_bad_unknown_module", PANAMA_MAIN, failWithWarning("WARNING: Unknown module: BAD specified to --enable-native-access"), @@ -160,6 +165,7 @@ public void testBadValue() throws Exception { "--illegal-native-access=deny"); } + @Test public void testDetailedWarningMessage() throws Exception { run("panama_enable_native_access_warn_jni", PANAMA_JNI, success() diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java index a14fd5c12d26..8bc353d14097 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ import jdk.test.lib.process.OutputAnalyzer; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class TestEnableNativeAccessBase { static final String MODULE_PATH = System.getProperty("jdk.module.path"); diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java index 2fccb2fa121e..b3118b1cd684 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @build TestEnableNativeAccessDynamic * panama_module/* NativeAccessDynamicMain - * @run testng/othervm/timeout=180 TestEnableNativeAccessDynamic + * @run junit/othervm/timeout=180 TestEnableNativeAccessDynamic * @summary Test for dynamically setting --enable-native-access flag for a module */ @@ -39,13 +39,13 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestEnableNativeAccessDynamic extends TestEnableNativeAccessBase { - @DataProvider(name = "succeedCases") public Object[][] succeedCases() { return new Object[][] { { "panama_enable_native_access", PANAMA_MAIN, successNoWarning() }, @@ -54,7 +54,6 @@ public Object[][] succeedCases() { }; } - @DataProvider(name = "failureCases") public Object[][] failureCases() { String errMsg = "Illegal native access from module panama_module"; return new Object[][] { @@ -92,13 +91,15 @@ OutputAnalyzer run(String action, String moduleAndCls, boolean enableNativeAcces return outputAnalyzer; } - @Test(dataProvider = "succeedCases") + @ParameterizedTest + @MethodSource("succeedCases") public void testSucceed(String action, String moduleAndCls, Result expectedResult) throws Exception { run(action, moduleAndCls, true, expectedResult, false); } - @Test(dataProvider = "failureCases") + @ParameterizedTest + @MethodSource("failureCases") public void testFailures(String action, String moduleAndCls, Result expectedResult) throws Exception { run(action, moduleAndCls, false, expectedResult, false); @@ -106,7 +107,8 @@ public void testFailures(String action, String moduleAndCls, // make sure that having a same named module in boot layer with native access // does not influence same named dynamic module. - @Test(dataProvider = "failureCases") + @ParameterizedTest + @MethodSource("failureCases") public void testFailuresWithPanamaModuleInBootLayer(String action, String moduleAndCls, Result expectedResult) throws Exception { run(action, moduleAndCls, false, expectedResult, true); diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java index 3522921bdd34..3bcd960ccd01 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java @@ -32,7 +32,7 @@ * @build TestEnableNativeAccessJarManifest * panama_module/* * org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule - * @run testng/native TestEnableNativeAccessJarManifest + * @run junit/native TestEnableNativeAccessJarManifest */ import java.nio.file.Files; @@ -47,16 +47,19 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.util.JarUtils; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestEnableNativeAccessJarManifest extends TestEnableNativeAccessBase { private static final String REINVOKER = "TestEnableNativeAccessJarManifest$Reinvoker"; static record Attribute(String name, String value) {} - @Test(dataProvider = "cases") + @ParameterizedTest + @MethodSource("cases") public void testEnableNativeAccessInJarManifest(String action, String cls, Result expectedResult, List attributes, List vmArgs, List programArgs) throws Exception { Manifest man = new Manifest(); @@ -89,7 +92,6 @@ public void testEnableNativeAccessInJarManifest(String action, String cls, Resul checkResult(expectedResult, outputAnalyzer); } - @DataProvider public Object[][] cases() { return new Object[][] { // simple cases where a jar contains a single main class with no dependencies diff --git a/test/jdk/java/foreign/handles/Driver.java b/test/jdk/java/foreign/handles/Driver.java index 63528e19dcbb..1bab9542e18a 100644 --- a/test/jdk/java/foreign/handles/Driver.java +++ b/test/jdk/java/foreign/handles/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,6 @@ /* * @test * @build invoker_module/* lookup_module/* - * @run testng/othervm --illegal-native-access=deny --enable-native-access=invoker_module + * @run junit/othervm --illegal-native-access=deny --enable-native-access=invoker_module * lookup_module/handle.lookup.MethodHandleLookup */ diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java index f41cf59b07f1..fa9729094cb9 100644 --- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java +++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,16 +37,19 @@ import java.nio.file.Path; import java.util.function.Consumer; -import org.testng.annotations.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MethodHandleLookup { - @Test(dataProvider = "restrictedMethods") + @ParameterizedTest + @MethodSource("restrictedMethods") public void testRestrictedHandles(MethodHandle handle, String testName) throws Throwable { new handle.invoker.MethodHandleInvoker().call(handle); } - @DataProvider(name = "restrictedMethods") static Object[][] restrictedMethods() { try { return new Object[][]{ diff --git a/test/jdk/java/foreign/handles/lookup_module/module-info.java b/test/jdk/java/foreign/handles/lookup_module/module-info.java index 54efcb071ef7..9a8fade97514 100644 --- a/test/jdk/java/foreign/handles/lookup_module/module-info.java +++ b/test/jdk/java/foreign/handles/lookup_module/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ open module lookup_module { - requires org.testng; + requires org.junit.platform.console.standalone; requires invoker_module; exports handle.lookup; } diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java index cb6c0c0bb9e5..22fead8c6e00 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,15 @@ * questions. */ -import org.testng.annotations.Test; import java.lang.foreign.SymbolLookup; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; /* * @test - * @run testng/othervm/native TestLoaderLookupJNI + * @run junit/othervm/native TestLoaderLookupJNI */ public class TestLoaderLookupJNI { diff --git a/test/jdk/java/foreign/loaderLookup/TestSymbolLookupFindOrThrow.java b/test/jdk/java/foreign/loaderLookup/TestSymbolLookupFindOrThrow.java index 146fdbbcf5a0..59f7720cb61f 100644 --- a/test/jdk/java/foreign/loaderLookup/TestSymbolLookupFindOrThrow.java +++ b/test/jdk/java/foreign/loaderLookup/TestSymbolLookupFindOrThrow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,9 @@ import java.lang.foreign.SymbolLookup; import java.util.NoSuchElementException; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; final class TestSymbolLookupFindOrThrow { @@ -44,7 +43,7 @@ final class TestSymbolLookupFindOrThrow { @Test void findOrThrow() { MemorySegment symbol = SymbolLookup.loaderLookup().findOrThrow("foo"); - Assertions.assertNotEquals(0, symbol.address()); + assertNotEquals(0, symbol.address()); } @Test diff --git a/test/jdk/java/foreign/nested/TestNested.java b/test/jdk/java/foreign/nested/TestNested.java index 70237bafc133..523fa630dd23 100644 --- a/test/jdk/java/foreign/nested/TestNested.java +++ b/test/jdk/java/foreign/nested/TestNested.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,9 @@ * @library ../ /test/lib * @requires jdk.foreign.linker != "FALLBACK" * @build NativeTestHelper - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestNested + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestNested */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -45,13 +43,19 @@ import java.util.Random; import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestNested extends NativeTestHelper { static { System.loadLibrary("Nested"); } - @Test(dataProvider = "nestedLayouts") + @ParameterizedTest + @MethodSource("nestedLayouts") public void testNested(GroupLayout layout) throws Throwable { try (Arena arena = Arena.ofConfined()) { Random random = new Random(0); @@ -73,7 +77,6 @@ public void testNested(GroupLayout layout) throws Throwable { } } - @DataProvider public static Object[][] nestedLayouts() { List layouts = List.of( S1, U1, U17, S2, S3, S4, S5, S6, U2, S7, U3, U4, U5, U6, U7, S8, S9, U8, U9, U10, S10, diff --git a/test/jdk/java/foreign/normalize/TestNormalize.java b/test/jdk/java/foreign/normalize/TestNormalize.java index b68e43c0705a..1de4da8e5c49 100644 --- a/test/jdk/java/foreign/normalize/TestNormalize.java +++ b/test/jdk/java/foreign/normalize/TestNormalize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,13 @@ /* * @test * @library ../ - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * -Xbatch * -XX:CompileCommand=dontinline,TestNormalize::doCall* * TestNormalize */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; @@ -45,9 +43,14 @@ import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_SHORT; -import static org.testng.Assert.assertEquals; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; // test normalization of smaller than int primitive types +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestNormalize extends NativeTestHelper { private static final Linker LINKER = Linker.nativeLinker(); @@ -98,7 +101,8 @@ public class TestNormalize extends NativeTestHelper { // When we do either of those, argument normalization should take place, so that the resulting value is sane (1). // After that we convert the value back to int again, the JVM can/will skip value normalization here. // We then check the high order bits of the resulting int. If argument normalization took place at (1), they should all be 0. - @Test(dataProvider = "cases") + @ParameterizedTest + @MethodSource("cases") public void testNormalize(ValueLayout layout, int testValue, int hobMask, MethodHandle toInt, MethodHandle saver) throws Throwable { // use actual type as parameter type to test upcall arg normalization FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(layout); @@ -125,8 +129,8 @@ public void testNormalize(ValueLayout layout, int testValue, int hobMask, Method private static void doCall(MethodHandle downcallHandle, MemorySegment upcallStub, int[] box, int dirtyValue, int hobMask) throws Throwable { int result = (int) downcallHandle.invokeExact(upcallStub, dirtyValue); - assertEquals(box[0] & hobMask, 0); // check normalized upcall arg - assertEquals(result & hobMask, 0); // check normalized downcall return value + assertEquals(0, box[0] & hobMask); // check normalized upcall arg + assertEquals(0, result & hobMask); // check normalized downcall return value } public static void saveBooleanAsInt(boolean b, int[] box) { @@ -159,7 +163,6 @@ public static int shortToInt(short s) { return s; } - @DataProvider public static Object[][] cases() { return new Object[][] { { JAVA_BOOLEAN, booleanToInt(true), BOOLEAN_HOB_MASK, BOOLEAN_TO_INT, SAVE_BOOLEAN_AS_INT }, @@ -171,7 +174,8 @@ public static Object[][] cases() { // test which int values are considered true and false // we currently convert any int with a non-zero first byte to true, otherwise false. - @Test(dataProvider = "bools") + @ParameterizedTest + @MethodSource("bools") public void testBool(int testValue, boolean expected) throws Throwable { MemorySegment addr = findNativeOrThrow("test"); MethodHandle target = LINKER.downcallHandle(addr, FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, JAVA_INT)); @@ -182,8 +186,8 @@ public void testBool(int testValue, boolean expected) throws Throwable { try (Arena arena = Arena.ofConfined()) { MemorySegment callback = LINKER.upcallStub(upcallTarget, FunctionDescriptor.ofVoid(JAVA_BOOLEAN), arena); boolean result = (boolean) target.invokeExact(callback, testValue); - assertEquals(box[0], expected); - assertEquals(result, expected); + assertEquals(expected, box[0]); + assertEquals(expected, result); } } @@ -191,7 +195,6 @@ private static void saveBoolean(boolean b, boolean[] box) { box[0] = b; } - @DataProvider public static Object[][] bools() { return new Object[][]{ { 0b10, true }, // zero least significant bit, but non-zero first byte diff --git a/test/jdk/java/foreign/normalize/TestNormalizeBooleanVarHandle.java b/test/jdk/java/foreign/normalize/TestNormalizeBooleanVarHandle.java index acca0d095c30..567fec7ccb88 100644 --- a/test/jdk/java/foreign/normalize/TestNormalizeBooleanVarHandle.java +++ b/test/jdk/java/foreign/normalize/TestNormalizeBooleanVarHandle.java @@ -23,11 +23,9 @@ /* * @test - * @run testng TestNormalizeBooleanVarHandle + * @run junit TestNormalizeBooleanVarHandle */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -38,14 +36,20 @@ import java.util.function.Predicate; import static java.lang.foreign.ValueLayout.*; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; // test normalization of smaller than int primitive types +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestNormalizeBooleanVarHandle { static final VarHandle VH = JAVA_BOOLEAN.varHandle(); - @Test(dataProvider = "bools") + @ParameterizedTest + @MethodSource("bools") public void testBool(Function segmentFactory, Predicate accessor, byte testValue, boolean expected) { try (Arena arena = Arena.ofConfined()) { @@ -53,11 +57,10 @@ public void testBool(Function segmentFactory, Predicate cases = new ArrayList<>(); for (Function segmentFactory : factories()) { diff --git a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java index 1f63d7bfe231..b3f23b1230d6 100644 --- a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java +++ b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,9 @@ /* * @test * @library ../ /test/lib - * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestPassHeapSegment + * @run junit/othervm/native --enable-native-access=ALL-UNNAMED TestPassHeapSegment */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; import java.lang.foreign.*; @@ -36,22 +34,32 @@ import static java.lang.foreign.ValueLayout.ADDRESS; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestPassHeapSegment extends UpcallTestHelper { static { System.loadLibrary("PassHeapSegment"); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void testNoHeapArgs() throws Throwable { MethodHandle handle = downcallHandle("test_args", FunctionDescriptor.ofVoid(ADDRESS)); MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); - handle.invoke(segment); // should throw + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + handle.invoke(segment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + @Test public void testNoHeapCaptureCallState() throws Throwable { MethodHandle handle = downcallHandle("test_args", FunctionDescriptor.ofVoid(ADDRESS), Linker.Option.captureCallState("errno")); @@ -59,11 +67,15 @@ public void testNoHeapCaptureCallState() throws Throwable { assert Linker.Option.captureStateLayout().byteAlignment() % 4 == 0; MemorySegment captureHeap = MemorySegment.ofArray(new int[(int) Linker.Option.captureStateLayout().byteSize() / 4]); MemorySegment segment = arena.allocateFrom(C_CHAR, new byte[]{ 0, 1, 2 }); - handle.invoke(captureHeap, segment); // should throw for captureHeap + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { + handle.invoke(captureHeap, segment); + }); + assertTrue(e.getMessage().matches(".*Heap segment not allowed.*")); } } - @Test(dataProvider = "specs") + @ParameterizedTest + @MethodSource("specs") public void testNoHeapReturns(boolean spec) throws IOException, InterruptedException { runInNewProcess(Runner.class, spec) .shouldNotHaveExitValue(0) @@ -87,7 +99,6 @@ public static MemorySegment target() { } } - @DataProvider public static Object[][] specs() { return new Object[][]{ { true }, diff --git a/test/jdk/java/foreign/virtual/TestVirtualCalls.java b/test/jdk/java/foreign/virtual/TestVirtualCalls.java index ddb4eb666949..931ce3ff5b19 100644 --- a/test/jdk/java/foreign/virtual/TestVirtualCalls.java +++ b/test/jdk/java/foreign/virtual/TestVirtualCalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @library ../ - * @run testng/othervm/native + * @run junit/othervm/native * --enable-native-access=ALL-UNNAMED * TestVirtualCalls */ @@ -35,9 +35,9 @@ import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; -import org.testng.annotations.*; - -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; public class TestVirtualCalls extends NativeTestHelper { @@ -60,14 +60,16 @@ public class TestVirtualCalls extends NativeTestHelper { @Test public void testVirtualCalls() throws Throwable { - assertEquals((int) func.invokeExact(funcA), 1); - assertEquals((int) func.invokeExact(funcB), 2); - assertEquals((int) func.invokeExact(funcC), 3); + assertEquals(1, (int) func.invokeExact(funcA)); + assertEquals(2, (int) func.invokeExact(funcB)); + assertEquals(3, (int) func.invokeExact(funcC)); } - @Test(expectedExceptions = NullPointerException.class) + @Test public void testNullTarget() throws Throwable { - int x = (int) func.invokeExact((MemorySegment)null); + assertThrows(NullPointerException.class, () -> { + int x = (int) func.invokeExact((MemorySegment)null); + }); } } diff --git a/test/jdk/java/lang/Object/ValueObjects.java b/test/jdk/java/lang/Object/ValueObjects.java index f84cee73a99f..50122d1a401d 100644 --- a/test/jdk/java/lang/Object/ValueObjects.java +++ b/test/jdk/java/lang/Object/ValueObjects.java @@ -74,6 +74,32 @@ protected V clone() throws CloneNotSupportedException { assertThrows(CloneNotSupportedException.class, obj::clone); } + /** + * Test the Object.clone method on a value object read from a flattened + * field. The read materializes the value from the embedded payload and + * clone returns it. + */ + @Test + void testCloneValueFromField() throws Exception { + value class V implements Cloneable { + int i; + V(int i) { this.i = i; } + @Override + protected V clone() throws CloneNotSupportedException { + return (V) super.clone(); + } + } + class Holder { + V v = new V(42); + } + var holder = new Holder(); + V read = holder.v; + V copy = read.clone(); + assertSame(read, copy); + assertEquals(42, copy.i); + assertSame(holder.v, holder.v.clone()); + } + /** * Test that the finalize method on a value class is not invoked by the GC. */ diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TestDescription.java b/test/jdk/java/lang/invoke/VarHandles/NullRestrictedValue.java similarity index 62% rename from test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TestDescription.java rename to test/jdk/java/lang/invoke/VarHandles/NullRestrictedValue.java index 556dcd28c8d2..be4222e08919 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_default/TestDescription.java +++ b/test/jdk/java/lang/invoke/VarHandles/NullRestrictedValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,8 @@ * questions. */ - -/* - * @test - * @modules java.base/jdk.internal.misc:+open - * - * @summary converted from VM Testbase metaspace/gc/firstGC_default. - * VM Testbase keywords: [nonconcurrent, quarantine] - * VM Testbase comments: 8208250 - * - * @library /vmTestbase /test/lib - * @run main/othervm - * -Xms200m - * -Xlog:gc+heap=trace,gc:gc.log - * -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions - * -XX:-VerifyBeforeExit - * -XX:-UseCompressedOops - * metaspace.gc.FirstGCTest - */ - +value record NullRestrictedValue(byte a, short b) { + static NullRestrictedValue of(byte a, short b) { + return new NullRestrictedValue(a, b); + } +} diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index 4c7a1ba90291..50801fcadef7 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessBoolean * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessBoolean @@ -52,17 +52,17 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { static final boolean static_final_v = true; - static boolean static_v; + static boolean static_v = true; - final boolean final_v = true; + final boolean final_v; boolean v; static final boolean static_final_v2 = true; - static boolean static_v2; + static boolean static_v2 = true; - final boolean final_v2 = true; + final boolean final_v2; boolean v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessBoolean() { + final_v = true; + v = true; + final_v2 = true; + v2 = true; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessBoolean recv, VarHandle vh // Lazy { boolean x = (boolean) vh.getAcquire(recv); - assertEquals(true, x, "getRelease boolean value"); + assertEquals(true, x, "getAcquire boolean value"); } // Opaque @@ -370,7 +377,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { boolean x = (boolean) vh.getAcquire(); - assertEquals(true, x, "getRelease boolean value"); + assertEquals(true, x, "getAcquire boolean value"); } // Opaque @@ -1415,6 +1422,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index 3a26f75d6cc4..abfe770f29af 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessByte * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessByte @@ -52,17 +52,17 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { static final byte static_final_v = (byte)0x01; - static byte static_v; + static byte static_v = (byte)0x01; - final byte final_v = (byte)0x01; + final byte final_v; byte v; static final byte static_final_v2 = (byte)0x01; - static byte static_v2; + static byte static_v2 = (byte)0x01; - final byte final_v2 = (byte)0x01; + final byte final_v2; byte v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessByte() { + final_v = (byte)0x01; + v = (byte)0x01; + final_v2 = (byte)0x01; + v2 = (byte)0x01; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessByte recv, VarHandle vh) { // Lazy { byte x = (byte) vh.getAcquire(recv); - assertEquals((byte)0x01, x, "getRelease byte value"); + assertEquals((byte)0x01, x, "getAcquire byte value"); } // Opaque @@ -359,7 +366,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { byte x = (byte) vh.getAcquire(); - assertEquals((byte)0x01, x, "getRelease byte value"); + assertEquals((byte)0x01, x, "getAcquire byte value"); } // Opaque @@ -603,7 +610,7 @@ static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) { vh.set(recv, (byte)0x01); byte o = (byte) vh.getAndAddRelease(recv, (byte)0x23); - assertEquals((byte)0x01, o, "getAndAddReleasebyte"); + assertEquals((byte)0x01, o, "getAndAddRelease byte"); byte x = (byte) vh.get(recv); assertEquals((byte)((byte)0x01 + (byte)0x23), x, "getAndAddRelease byte value"); } @@ -911,7 +918,7 @@ static void testStaticField(VarHandle vh) { vh.set((byte)0x01); byte o = (byte) vh.getAndAddRelease((byte)0x23); - assertEquals((byte)0x01, o, "getAndAddReleasebyte"); + assertEquals((byte)0x01, o, "getAndAddRelease byte"); byte x = (byte) vh.get(); assertEquals((byte)((byte)0x01 + (byte)0x23), x, "getAndAddRelease byte value"); } @@ -1222,7 +1229,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, (byte)0x01); byte o = (byte) vh.getAndAddRelease(array, i, (byte)0x23); - assertEquals((byte)0x01, o, "getAndAddReleasebyte"); + assertEquals((byte)0x01, o, "getAndAddRelease byte"); byte x = (byte) vh.get(array, i); assertEquals((byte)((byte)0x01 + (byte)0x23), x, "getAndAddRelease byte value"); } @@ -1452,6 +1459,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index b6e54e3e8582..e4836c9a6f0b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessChar * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessChar @@ -52,17 +52,17 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { static final char static_final_v = '\u0123'; - static char static_v; + static char static_v = '\u0123'; - final char final_v = '\u0123'; + final char final_v; char v; static final char static_final_v2 = '\u0123'; - static char static_v2; + static char static_v2 = '\u0123'; - final char final_v2 = '\u0123'; + final char final_v2; char v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessChar() { + final_v = '\u0123'; + v = '\u0123'; + final_v2 = '\u0123'; + v2 = '\u0123'; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) { // Lazy { char x = (char) vh.getAcquire(recv); - assertEquals('\u0123', x, "getRelease char value"); + assertEquals('\u0123', x, "getAcquire char value"); } // Opaque @@ -359,7 +366,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { char x = (char) vh.getAcquire(); - assertEquals('\u0123', x, "getRelease char value"); + assertEquals('\u0123', x, "getAcquire char value"); } // Opaque @@ -603,7 +610,7 @@ static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { vh.set(recv, '\u0123'); char o = (char) vh.getAndAddRelease(recv, '\u4567'); - assertEquals('\u0123', o, "getAndAddReleasechar"); + assertEquals('\u0123', o, "getAndAddRelease char"); char x = (char) vh.get(recv); assertEquals((char)('\u0123' + '\u4567'), x, "getAndAddRelease char value"); } @@ -911,7 +918,7 @@ static void testStaticField(VarHandle vh) { vh.set('\u0123'); char o = (char) vh.getAndAddRelease('\u4567'); - assertEquals('\u0123', o, "getAndAddReleasechar"); + assertEquals('\u0123', o, "getAndAddRelease char"); char x = (char) vh.get(); assertEquals((char)('\u0123' + '\u4567'), x, "getAndAddRelease char value"); } @@ -1222,7 +1229,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, '\u0123'); char o = (char) vh.getAndAddRelease(array, i, '\u4567'); - assertEquals('\u0123', o, "getAndAddReleasechar"); + assertEquals('\u0123', o, "getAndAddRelease char"); char x = (char) vh.get(array, i); assertEquals((char)('\u0123' + '\u4567'), x, "getAndAddRelease char value"); } @@ -1452,6 +1459,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index 6c4f76d00899..d5b2a02418b6 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessDouble * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessDouble * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessDouble @@ -52,17 +52,17 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { static final double static_final_v = 1.0d; - static double static_v; + static double static_v = 1.0d; - final double final_v = 1.0d; + final double final_v; double v; static final double static_final_v2 = 1.0d; - static double static_v2; + static double static_v2 = 1.0d; - final double final_v2 = 1.0d; + final double final_v2; double v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessDouble() { + final_v = 1.0d; + v = 1.0d; + final_v2 = 1.0d; + v2 = 1.0d; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessDouble recv, VarHandle vh) // Lazy { double x = (double) vh.getAcquire(recv); - assertEquals(1.0d, x, "getRelease double value"); + assertEquals(1.0d, x, "getAcquire double value"); } // Opaque @@ -394,7 +401,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { double x = (double) vh.getAcquire(); - assertEquals(1.0d, x, "getRelease double value"); + assertEquals(1.0d, x, "getAcquire double value"); } // Opaque @@ -673,7 +680,7 @@ static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) { vh.set(recv, 1.0d); double o = (double) vh.getAndAddRelease(recv, 2.0d); - assertEquals(1.0d, o, "getAndAddReleasedouble"); + assertEquals(1.0d, o, "getAndAddRelease double"); double x = (double) vh.get(recv); assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value"); } @@ -933,7 +940,7 @@ static void testStaticField(VarHandle vh) { vh.set(1.0d); double o = (double) vh.getAndAddRelease(2.0d); - assertEquals(1.0d, o, "getAndAddReleasedouble"); + assertEquals(1.0d, o, "getAndAddRelease double"); double x = (double) vh.get(); assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value"); } @@ -1196,7 +1203,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, 1.0d); double o = (double) vh.getAndAddRelease(array, i, 2.0d); - assertEquals(1.0d, o, "getAndAddReleasedouble"); + assertEquals(1.0d, o, "getAndAddRelease double"); double x = (double) vh.get(array, i); assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value"); } @@ -1343,6 +1350,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index c9800f464d07..40eee3fadcfe 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessFloat * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessFloat * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessFloat @@ -52,17 +52,17 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { static final float static_final_v = 1.0f; - static float static_v; + static float static_v = 1.0f; - final float final_v = 1.0f; + final float final_v; float v; static final float static_final_v2 = 1.0f; - static float static_v2; + static float static_v2 = 1.0f; - final float final_v2 = 1.0f; + final float final_v2; float v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessFloat() { + final_v = 1.0f; + v = 1.0f; + final_v2 = 1.0f; + v2 = 1.0f; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessFloat recv, VarHandle vh) // Lazy { float x = (float) vh.getAcquire(recv); - assertEquals(1.0f, x, "getRelease float value"); + assertEquals(1.0f, x, "getAcquire float value"); } // Opaque @@ -394,7 +401,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { float x = (float) vh.getAcquire(); - assertEquals(1.0f, x, "getRelease float value"); + assertEquals(1.0f, x, "getAcquire float value"); } // Opaque @@ -673,7 +680,7 @@ static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) { vh.set(recv, 1.0f); float o = (float) vh.getAndAddRelease(recv, 2.0f); - assertEquals(1.0f, o, "getAndAddReleasefloat"); + assertEquals(1.0f, o, "getAndAddRelease float"); float x = (float) vh.get(recv); assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value"); } @@ -933,7 +940,7 @@ static void testStaticField(VarHandle vh) { vh.set(1.0f); float o = (float) vh.getAndAddRelease(2.0f); - assertEquals(1.0f, o, "getAndAddReleasefloat"); + assertEquals(1.0f, o, "getAndAddRelease float"); float x = (float) vh.get(); assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value"); } @@ -1196,7 +1203,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, 1.0f); float o = (float) vh.getAndAddRelease(array, i, 2.0f); - assertEquals(1.0f, o, "getAndAddReleasefloat"); + assertEquals(1.0f, o, "getAndAddRelease float"); float x = (float) vh.get(array, i); assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value"); } @@ -1343,6 +1350,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index 3f06311988ec..de390262f7cc 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessInt * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessInt * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessInt @@ -52,17 +52,17 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { static final int static_final_v = 0x01234567; - static int static_v; + static int static_v = 0x01234567; - final int final_v = 0x01234567; + final int final_v; int v; static final int static_final_v2 = 0x01234567; - static int static_v2; + static int static_v2 = 0x01234567; - final int final_v2 = 0x01234567; + final int final_v2; int v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessInt() { + final_v = 0x01234567; + v = 0x01234567; + final_v2 = 0x01234567; + v2 = 0x01234567; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessInt recv, VarHandle vh) { // Lazy { int x = (int) vh.getAcquire(recv); - assertEquals(0x01234567, x, "getRelease int value"); + assertEquals(0x01234567, x, "getAcquire int value"); } // Opaque @@ -359,7 +366,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { int x = (int) vh.getAcquire(); - assertEquals(0x01234567, x, "getRelease int value"); + assertEquals(0x01234567, x, "getAcquire int value"); } // Opaque @@ -603,7 +610,7 @@ static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) { vh.set(recv, 0x01234567); int o = (int) vh.getAndAddRelease(recv, 0x89ABCDEF); - assertEquals(0x01234567, o, "getAndAddReleaseint"); + assertEquals(0x01234567, o, "getAndAddRelease int"); int x = (int) vh.get(recv); assertEquals((int)(0x01234567 + 0x89ABCDEF), x, "getAndAddRelease int value"); } @@ -911,7 +918,7 @@ static void testStaticField(VarHandle vh) { vh.set(0x01234567); int o = (int) vh.getAndAddRelease(0x89ABCDEF); - assertEquals(0x01234567, o, "getAndAddReleaseint"); + assertEquals(0x01234567, o, "getAndAddRelease int"); int x = (int) vh.get(); assertEquals((int)(0x01234567 + 0x89ABCDEF), x, "getAndAddRelease int value"); } @@ -1222,7 +1229,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, 0x01234567); int o = (int) vh.getAndAddRelease(array, i, 0x89ABCDEF); - assertEquals(0x01234567, o, "getAndAddReleaseint"); + assertEquals(0x01234567, o, "getAndAddRelease int"); int x = (int) vh.get(array, i); assertEquals((int)(0x01234567 + 0x89ABCDEF), x, "getAndAddRelease int value"); } @@ -1452,6 +1459,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index 7ed1a14bdc8f..b5fa2ec390d1 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessLong * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessLong * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessLong @@ -52,17 +52,17 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { static final long static_final_v = 0x0123456789ABCDEFL; - static long static_v; + static long static_v = 0x0123456789ABCDEFL; - final long final_v = 0x0123456789ABCDEFL; + final long final_v; long v; static final long static_final_v2 = 0x0123456789ABCDEFL; - static long static_v2; + static long static_v2 = 0x0123456789ABCDEFL; - final long final_v2 = 0x0123456789ABCDEFL; + final long final_v2; long v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessLong() { + final_v = 0x0123456789ABCDEFL; + v = 0x0123456789ABCDEFL; + final_v2 = 0x0123456789ABCDEFL; + v2 = 0x0123456789ABCDEFL; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessLong recv, VarHandle vh) { // Lazy { long x = (long) vh.getAcquire(recv); - assertEquals(0x0123456789ABCDEFL, x, "getRelease long value"); + assertEquals(0x0123456789ABCDEFL, x, "getAcquire long value"); } // Opaque @@ -359,7 +366,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { long x = (long) vh.getAcquire(); - assertEquals(0x0123456789ABCDEFL, x, "getRelease long value"); + assertEquals(0x0123456789ABCDEFL, x, "getAcquire long value"); } // Opaque @@ -603,7 +610,7 @@ static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) { vh.set(recv, 0x0123456789ABCDEFL); long o = (long) vh.getAndAddRelease(recv, 0xCAFEBABECAFEBABEL); - assertEquals(0x0123456789ABCDEFL, o, "getAndAddReleaselong"); + assertEquals(0x0123456789ABCDEFL, o, "getAndAddRelease long"); long x = (long) vh.get(recv); assertEquals((long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), x, "getAndAddRelease long value"); } @@ -911,7 +918,7 @@ static void testStaticField(VarHandle vh) { vh.set(0x0123456789ABCDEFL); long o = (long) vh.getAndAddRelease(0xCAFEBABECAFEBABEL); - assertEquals(0x0123456789ABCDEFL, o, "getAndAddReleaselong"); + assertEquals(0x0123456789ABCDEFL, o, "getAndAddRelease long"); long x = (long) vh.get(); assertEquals((long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), x, "getAndAddRelease long value"); } @@ -1222,7 +1229,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, 0x0123456789ABCDEFL); long o = (long) vh.getAndAddRelease(array, i, 0xCAFEBABECAFEBABEL); - assertEquals(0x0123456789ABCDEFL, o, "getAndAddReleaselong"); + assertEquals(0x0123456789ABCDEFL, o, "getAndAddRelease long"); long x = (long) vh.get(array, i); assertEquals((long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), x, "getAndAddRelease long value"); } @@ -1452,6 +1459,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessNullRestrictedValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessNullRestrictedValue.java new file mode 100644 index 000000000000..346c7beb1934 --- /dev/null +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessNullRestrictedValue.java @@ -0,0 +1,1659 @@ +/* + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +/* + * @test + * @enablePreview + * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value + * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessNullRestrictedValue + * + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds + * + * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessNullRestrictedValue + * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessNullRestrictedValue + * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestAccessNullRestrictedValue + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class VarHandleTestAccessNullRestrictedValue extends VarHandleBaseTest { + static final @NullRestricted NullRestrictedValue static_final_v = NullRestrictedValue.of((byte)20,(short)1854); + + static @NullRestricted NullRestrictedValue static_v = NullRestrictedValue.of((byte)20,(short)1854); + + final @NullRestricted NullRestrictedValue final_v; + + @NullRestricted NullRestrictedValue v; + + static final @NullRestricted NullRestrictedValue static_final_v2 = NullRestrictedValue.of((byte)20,(short)1854); + + static @NullRestricted NullRestrictedValue static_v2 = NullRestrictedValue.of((byte)20,(short)1854); + + final @NullRestricted NullRestrictedValue final_v2; + + @NullRestricted NullRestrictedValue v2; + + VarHandle vhFinalField; + + VarHandle vhField; + + VarHandle vhStaticField; + + VarHandle vhStaticFinalField; + + VarHandle vhArray; + + VarHandle vhArrayObject; + + public VarHandleTestAccessNullRestrictedValue() { + final_v = NullRestrictedValue.of((byte)20,(short)1854); + v = NullRestrictedValue.of((byte)20,(short)1854); + final_v2 = NullRestrictedValue.of((byte)20,(short)1854); + v2 = NullRestrictedValue.of((byte)20,(short)1854); + super(); + } + + VarHandle[] allocate(boolean same) { + List vhs = new ArrayList<>(); + + String postfix = same ? "" : "2"; + VarHandle vh; + try { + vh = MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "final_v" + postfix, NullRestrictedValue.class); + vhs.add(vh); + + vh = MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "v" + postfix, NullRestrictedValue.class); + vhs.add(vh); + + vh = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_final_v" + postfix, NullRestrictedValue.class); + vhs.add(vh); + + vh = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_v" + postfix, NullRestrictedValue.class); + vhs.add(vh); + + if (same) { + vh = MethodHandles.arrayElementVarHandle(NullRestrictedValue[].class); + } + else { + vh = MethodHandles.arrayElementVarHandle(String[].class); + } + vhs.add(vh); + } catch (Exception e) { + throw new InternalError(e); + } + return vhs.toArray(new VarHandle[0]); + } + + @BeforeAll + public void setup() throws Exception { + vhFinalField = MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "final_v", NullRestrictedValue.class); + + vhField = MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "v", NullRestrictedValue.class); + + vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_final_v", NullRestrictedValue.class); + + vhStaticField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_v", NullRestrictedValue.class); + + vhArray = MethodHandles.arrayElementVarHandle(NullRestrictedValue[].class); + vhArrayObject = MethodHandles.arrayElementVarHandle(Object[].class); + } + + public Object[][] varHandlesProvider() throws Exception { + List vhs = new ArrayList<>(); + vhs.add(vhField); + vhs.add(vhStaticField); + vhs.add(vhArray); + + return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new); + } + + @Test + public void testEquals() { + VarHandle[] vhs1 = allocate(true); + VarHandle[] vhs2 = allocate(true); + + for (int i = 0; i < vhs1.length; i++) { + for (int j = 0; j < vhs1.length; j++) { + if (i != j) { + assertNotEquals(vhs1[i], vhs1[j]); + assertNotEquals(vhs1[i], vhs2[j]); + } + } + } + + VarHandle[] vhs3 = allocate(false); + for (int i = 0; i < vhs1.length; i++) { + assertNotEquals(vhs1[i], vhs3[i]); + } + } + + @ParameterizedTest + @MethodSource("varHandlesProvider") + public void testIsAccessModeSupported(VarHandle vh) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } + + public Object[][] typesProvider() throws Exception { + List types = new ArrayList<>(); + types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessNullRestrictedValue.class)}); + types.add(new Object[] {vhStaticField, Arrays.asList()}); + types.add(new Object[] {vhArray, Arrays.asList(NullRestrictedValue[].class, int.class)}); + + return types.stream().toArray(Object[][]::new); + } + + @ParameterizedTest + @MethodSource("typesProvider") + public void testTypes(VarHandle vh, List> pts) { + assertEquals(NullRestrictedValue.class, vh.varType()); + + assertEquals(pts, vh.coordinateTypes()); + + testTypes(vh); + } + + @Test + public void testLookupInstanceToStatic() { + checkIAE("Lookup of static final field to instance final field", () -> { + MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "final_v", NullRestrictedValue.class); + }); + + checkIAE("Lookup of static field to instance field", () -> { + MethodHandles.lookup().findStaticVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "v", NullRestrictedValue.class); + }); + } + + @Test + public void testLookupStaticToInstance() { + checkIAE("Lookup of instance final field to static final field", () -> { + MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_final_v", NullRestrictedValue.class); + }); + + checkIAE("Lookup of instance field to static field", () -> { + vhStaticField = MethodHandles.lookup().findVarHandle( + VarHandleTestAccessNullRestrictedValue.class, "static_v", NullRestrictedValue.class); + }); + } + + public Object[][] accessTestCaseProvider() throws Exception { + List> cases = new ArrayList<>(); + + cases.add(new VarHandleAccessTestCase("Instance final field", + vhFinalField, vh -> testInstanceFinalField(this, vh))); + cases.add(new VarHandleAccessTestCase("Instance final field unsupported", + vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh), + false)); + + cases.add(new VarHandleAccessTestCase("Static final field", + vhStaticFinalField, VarHandleTestAccessNullRestrictedValue::testStaticFinalField)); + cases.add(new VarHandleAccessTestCase("Static final field unsupported", + vhStaticFinalField, VarHandleTestAccessNullRestrictedValue::testStaticFinalFieldUnsupported, + false)); + + cases.add(new VarHandleAccessTestCase("Instance field", + vhField, vh -> testInstanceField(this, vh))); + cases.add(new VarHandleAccessTestCase("Instance field unsupported", + vhField, vh -> testInstanceFieldUnsupported(this, vh), + false)); + cases.add(new VarHandleAccessTestCase("Instance field null pointer exception", + vhField, vh -> testInstanceFieldNullPointerException(this, vh), + false)); + + cases.add(new VarHandleAccessTestCase("Static field", + vhStaticField, VarHandleTestAccessNullRestrictedValue::testStaticField)); + cases.add(new VarHandleAccessTestCase("Static field unsupported", + vhStaticField, VarHandleTestAccessNullRestrictedValue::testStaticFieldUnsupported, + false)); + cases.add(new VarHandleAccessTestCase("Static field null pointer exception", + vhStaticField, VarHandleTestAccessNullRestrictedValue::testStaticFieldNullPointerException, + false)); + + cases.add(new VarHandleAccessTestCase("Array", + vhArray, VarHandleTestAccessNullRestrictedValue::testArray)); + cases.add(new VarHandleAccessTestCase("Array Object[]", + vhArrayObject, VarHandleTestAccessNullRestrictedValue::testArray)); + cases.add(new VarHandleAccessTestCase("Array unsupported", + vhArray, VarHandleTestAccessNullRestrictedValue::testArrayUnsupported, + false)); + cases.add(new VarHandleAccessTestCase("Array index out of bounds", + vhArray, VarHandleTestAccessNullRestrictedValue::testArrayIndexOutOfBounds, + false)); + cases.add(new VarHandleAccessTestCase("Array store exception", + vhArrayObject, VarHandleTestAccessNullRestrictedValue::testArrayStoreException, + false)); + cases.add(new VarHandleAccessTestCase("Array null pointer exception", + vhArrayObject, VarHandleTestAccessNullRestrictedValue::testArrayNullPointerException, + false)); + // Work around issue with jtreg summary reporting which truncates + // the String result of Object.toString to 30 characters, hence + // the first dummy argument + return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); + } + + @ParameterizedTest + @MethodSource("accessTestCaseProvider") + public void testAccess(String desc, AccessTestCase atc) throws Throwable { + T t = atc.get(); + int iters = atc.requiresLoop() ? ITERS : 1; + for (int c = 0; c < iters; c++) { + atc.testAccess(t); + } + } + + static void testInstanceFinalField(VarHandleTestAccessNullRestrictedValue recv, VarHandle vh) { + // Plain + { + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "get NullRestrictedValue value"); + } + + + // Volatile + { + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getVolatile NullRestrictedValue value"); + } + + // Lazy + { + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getAcquire NullRestrictedValue value"); + } + + // Opaque + { + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getOpaque NullRestrictedValue value"); + } + } + + static void testInstanceFinalFieldUnsupported(VarHandleTestAccessNullRestrictedValue recv, VarHandle vh) { + checkUOE(() -> { + vh.set(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setVolatile(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setRelease(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setOpaque(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAdd(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOr(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAnd(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXor(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + + static void testStaticFinalField(VarHandle vh) { + // Plain + { + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "get NullRestrictedValue value"); + } + + + // Volatile + { + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getVolatile NullRestrictedValue value"); + } + + // Lazy + { + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getAcquire NullRestrictedValue value"); + } + + // Opaque + { + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "getOpaque NullRestrictedValue value"); + } + } + + static void testStaticFinalFieldUnsupported(VarHandle vh) { + checkUOE(() -> { + vh.set(NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setVolatile(NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setRelease(NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkUOE(() -> { + vh.setOpaque(NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAdd(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOr(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAnd(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXor(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + + static void testInstanceField(VarHandleTestAccessNullRestrictedValue recv, VarHandle vh) { + // Plain + { + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "set NullRestrictedValue value"); + } + + + // Volatile + { + vh.setVolatile(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + vh.setRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + vh.setOpaque(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = vh.compareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = vh.compareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetPlain(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSet(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetAcquire(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetRelease(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + + static void testInstanceFieldUnsupported(VarHandleTestAccessNullRestrictedValue recv, VarHandle vh) { + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAdd(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOr(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAnd(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXor(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + + static void testStaticField(VarHandle vh) { + // Plain + { + vh.set(NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "set NullRestrictedValue value"); + } + + + // Volatile + { + vh.setVolatile(NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + vh.setRelease(NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + vh.setOpaque(NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + vh.set(NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = vh.compareAndSet(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = vh.compareAndSet(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetPlain(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSet(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + vh.set(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSet(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + vh.set(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetAcquire(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + vh.set(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetRelease(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + + static void testStaticFieldUnsupported(VarHandle vh) { + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAdd(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOr(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAnd(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXor(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + + static void testArray(VarHandle vh) { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + for (int i = 0; i < array.length; i++) { + // Plain + { + vh.set(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "get NullRestrictedValue value"); + } + + + // Volatile + { + vh.setVolatile(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + vh.setRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + vh.setOpaque(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + vh.set(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = vh.compareAndSet(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = vh.compareAndSet(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetPlain(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + vh.set(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSet(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + vh.set(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetAcquire(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + vh.set(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetRelease(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + } + + static void testArrayUnsupported(VarHandle vh) { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + int i = 0; + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAdd(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndAddRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOr(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseOrRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAnd(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseAndRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXor(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorAcquire(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkUOE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndBitwiseXorRelease(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) { + final int ci = i; + + checkAIOOBE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, ci); + }); + + checkAIOOBE(() -> { + vh.set(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(array, ci); + }); + + checkAIOOBE(() -> { + vh.setVolatile(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(array, ci); + }); + + checkAIOOBE(() -> { + vh.setRelease(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(array, ci); + }); + + checkAIOOBE(() -> { + vh.setOpaque(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchange(array, ci, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, ci, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue r = (NullRestrictedValue) vh.compareAndExchangeRelease(array, ci, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkAIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkAIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkAIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSet(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetAcquire(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + checkAIOOBE(() -> { + NullRestrictedValue o = (NullRestrictedValue) vh.getAndSetRelease(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + + + } + } + + static void testArrayStoreException(VarHandle vh) throws Throwable { + Object[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + Arrays.fill(array, NullRestrictedValue.of((byte)20,(short)1854)); + Object value = new Object(); + + // Set + checkASE(() -> { + vh.set(array, 0, value); + }); + + // SetVolatile + checkASE(() -> { + vh.setVolatile(array, 0, value); + }); + + // SetOpaque + checkASE(() -> { + vh.setOpaque(array, 0, value); + }); + + // SetRelease + checkASE(() -> { + vh.setRelease(array, 0, value); + }); + + // CompareAndSet + checkASE(() -> { + boolean r = vh.compareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSet + checkASE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetVolatile + checkASE(() -> { + boolean r = vh.weakCompareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetAcquire + checkASE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetRelease + checkASE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchange + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeAcquire + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeRelease + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // GetAndSet + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(array, 0, value); + }); + + // GetAndSetAcquire + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(array, 0, value); + }); + + // GetAndSetRelease + checkASE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(array, 0, value); + }); + } + + static void testInstanceFieldNullPointerException(VarHandleTestAccessNullRestrictedValue recv, VarHandle vh) throws Throwable { + NullRestrictedValue value = null; + + // Set + checkNPE(() -> { + vh.set(recv, value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(recv, value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(recv, value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(recv, value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchange + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // GetAndSet + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(recv, value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(recv, value); + }); + + // GetAndSetRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(recv, value); + }); + } + + static void testStaticFieldNullPointerException(VarHandle vh) throws Throwable { + NullRestrictedValue value = null; + + // Set + checkNPE(() -> { + vh.set(value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchange + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // GetAndSet + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(value); + }); + + // GetAndSetRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(value); + }); + } + + static void testArrayNullPointerException(VarHandle vh) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue value = null; + + // Set + checkNPE(() -> { + vh.set(array, 0, value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(array, 0, value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(array, 0, value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(array, 0, value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchange + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + + // GetAndSet + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(array, 0, value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(array, 0, value); + }); + + // GetAndSetRelease + checkNPE(() -> { + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(array, 0, value); + }); + } +} + diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index f3f5401584df..31beeb6e31f2 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessShort * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessShort * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessShort @@ -52,17 +52,17 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { static final short static_final_v = (short)0x0123; - static short static_v; + static short static_v = (short)0x0123; - final short final_v = (short)0x0123; + final short final_v; short v; static final short static_final_v2 = (short)0x0123; - static short static_v2; + static short static_v2 = (short)0x0123; - final short final_v2 = (short)0x0123; + final short final_v2; short v2; @@ -76,6 +76,13 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestAccessShort() { + final_v = (short)0x0123; + v = (short)0x0123; + final_v2 = (short)0x0123; + v2 = (short)0x0123; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -310,7 +317,7 @@ static void testInstanceFinalField(VarHandleTestAccessShort recv, VarHandle vh) // Lazy { short x = (short) vh.getAcquire(recv); - assertEquals((short)0x0123, x, "getRelease short value"); + assertEquals((short)0x0123, x, "getAcquire short value"); } // Opaque @@ -359,7 +366,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { short x = (short) vh.getAcquire(); - assertEquals((short)0x0123, x, "getRelease short value"); + assertEquals((short)0x0123, x, "getAcquire short value"); } // Opaque @@ -603,7 +610,7 @@ static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) { vh.set(recv, (short)0x0123); short o = (short) vh.getAndAddRelease(recv, (short)0x4567); - assertEquals((short)0x0123, o, "getAndAddReleaseshort"); + assertEquals((short)0x0123, o, "getAndAddRelease short"); short x = (short) vh.get(recv); assertEquals((short)((short)0x0123 + (short)0x4567), x, "getAndAddRelease short value"); } @@ -911,7 +918,7 @@ static void testStaticField(VarHandle vh) { vh.set((short)0x0123); short o = (short) vh.getAndAddRelease((short)0x4567); - assertEquals((short)0x0123, o, "getAndAddReleaseshort"); + assertEquals((short)0x0123, o, "getAndAddRelease short"); short x = (short) vh.get(); assertEquals((short)((short)0x0123 + (short)0x4567), x, "getAndAddRelease short value"); } @@ -1222,7 +1229,7 @@ static void testArray(VarHandle vh) { vh.set(array, i, (short)0x0123); short o = (short) vh.getAndAddRelease(array, i, (short)0x4567); - assertEquals((short)0x0123, o, "getAndAddReleaseshort"); + assertEquals((short)0x0123, o, "getAndAddRelease short"); short x = (short) vh.get(array, i); assertEquals((short)((short)0x0123 + (short)0x4567), x, "getAndAddRelease short value"); } @@ -1452,6 +1459,5 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } - } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 764145624855..b720ce80d649 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @test * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessString * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessString * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessString @@ -52,17 +52,17 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { static final String static_final_v = "foo"; - static String static_v; + static String static_v = "foo"; - final String final_v = "foo"; + final String final_v; String v; static final String static_final_v2 = "foo"; - static String static_v2; + static String static_v2 = "foo"; - final String final_v2 = "foo"; + final String final_v2; String v2; @@ -78,6 +78,14 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { VarHandle vhArrayObject; + public VarHandleTestAccessString() { + final_v = "foo"; + v = "foo"; + final_v2 = "foo"; + v2 = "foo"; + super(); + } + VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -317,7 +325,7 @@ static void testInstanceFinalField(VarHandleTestAccessString recv, VarHandle vh) // Lazy { String x = (String) vh.getAcquire(recv); - assertEquals("foo", x, "getRelease String value"); + assertEquals("foo", x, "getAcquire String value"); } // Opaque @@ -412,7 +420,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { String x = (String) vh.getAcquire(); - assertEquals("foo", x, "getRelease String value"); + assertEquals("foo", x, "getAcquire String value"); } // Opaque @@ -1340,57 +1348,57 @@ static void testArrayStoreException(VarHandle vh) throws Throwable { }); // CompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.compareAndSet(array, 0, "foo", value); }); // WeakCompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetPlain(array, 0, "foo", value); }); // WeakCompareAndSetVolatile - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSet(array, 0, "foo", value); }); // WeakCompareAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", value); }); // WeakCompareAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", value); }); // CompareAndExchange - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.compareAndExchange(array, 0, "foo", value); }); // CompareAndExchangeAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", value); }); // CompareAndExchangeRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", value); }); // GetAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.getAndSet(array, 0, value); }); // GetAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.getAndSetAcquire(array, 0, value); }); // GetAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { String x = (String) vh.getAndSetRelease(array, 0, value); }); } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessValue.java index a2aec4d3dbc9..db743f7a3349 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessValue.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,11 @@ * @test * @enablePreview * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value * @run junit/othervm -Diters=10 -Xint VarHandleTestAccessValue * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccessValue * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccessValue @@ -54,17 +55,17 @@ public class VarHandleTestAccessValue extends VarHandleBaseTest { static final Value static_final_v = Value.getInstance(10); - static Value static_v; + static Value static_v = Value.getInstance(10); - final Value final_v = Value.getInstance(10); + final Value final_v; Value v; static final Value static_final_v2 = Value.getInstance(10); - static Value static_v2; + static Value static_v2 = Value.getInstance(10); - final Value final_v2 = Value.getInstance(10); + final Value final_v2; Value v2; @@ -80,6 +81,14 @@ public class VarHandleTestAccessValue extends VarHandleBaseTest { VarHandle vhArrayObject; + public VarHandleTestAccessValue() { + final_v = Value.getInstance(10); + v = Value.getInstance(10); + final_v2 = Value.getInstance(10); + v2 = Value.getInstance(10); + super(); + } + VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -319,7 +328,7 @@ static void testInstanceFinalField(VarHandleTestAccessValue recv, VarHandle vh) // Lazy { Value x = (Value) vh.getAcquire(recv); - assertEquals(Value.getInstance(10), x, "getRelease Value value"); + assertEquals(Value.getInstance(10), x, "getAcquire Value value"); } // Opaque @@ -414,7 +423,7 @@ static void testStaticFinalField(VarHandle vh) { // Lazy { Value x = (Value) vh.getAcquire(); - assertEquals(Value.getInstance(10), x, "getRelease Value value"); + assertEquals(Value.getInstance(10), x, "getAcquire Value value"); } // Opaque @@ -1342,57 +1351,57 @@ static void testArrayStoreException(VarHandle vh) throws Throwable { }); // CompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.compareAndSet(array, 0, Value.getInstance(10), value); }); // WeakCompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetPlain(array, 0, Value.getInstance(10), value); }); // WeakCompareAndSetVolatile - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSet(array, 0, Value.getInstance(10), value); }); // WeakCompareAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, 0, Value.getInstance(10), value); }); // WeakCompareAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetRelease(array, 0, Value.getInstance(10), value); }); // CompareAndExchange - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.compareAndExchange(array, 0, Value.getInstance(10), value); }); // CompareAndExchangeAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.compareAndExchangeAcquire(array, 0, Value.getInstance(10), value); }); // CompareAndExchangeRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.compareAndExchangeRelease(array, 0, Value.getInstance(10), value); }); // GetAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.getAndSet(array, 0, value); }); // GetAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.getAndSetAcquire(array, 0, value); }); // GetAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { Value x = (Value) vh.getAndSetRelease(array, 0, value); }); } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index 26ac4aab893c..6dfe05e6e0af 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsChar * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsChar @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -820,7 +820,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { char x = (char) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease char value"); + assertEquals(v, x, "getAcquire char value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index a9e1e603c5d3..3be3bb800e05 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsDouble * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsDouble @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -1122,7 +1122,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { double x = (double) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease double value"); + assertEquals(v, x, "getAcquire double value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index 486487518e93..759bd264f876 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsFloat * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsFloat @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -1122,7 +1122,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { float x = (float) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease float value"); + assertEquals(v, x, "getAcquire float value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index ce55c3d5e31c..da8094154cd4 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsInt * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsInt @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -1388,7 +1388,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { int x = (int) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease int value"); + assertEquals(v, x, "getAcquire int value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index 763703b60798..793f945722ae 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsLong * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsLong @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -1388,7 +1388,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { long x = (long) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease long value"); + assertEquals(v, x, "getAcquire long value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 7a3bc069c224..305139856dfd 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsShort * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsShort @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -73,12 +73,12 @@ public List setupVarHandleSources(boolean same) { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -820,7 +820,7 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { // Lazy { short x = (short) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease short value"); + assertEquals(v, x, "getAcquire short value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java index 5c1eba506e90..eb579029e367 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessBoolean */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessBoolean extends VarHandleBaseTest { static final boolean static_final_v = true; - static boolean static_v; + static boolean static_v = true; - final boolean final_v = true; + final boolean final_v; boolean v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessBoolean extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessBoolean() { + final_v = true; + v = true; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handl // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, true); + boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, false); assertEquals(true, o, "getAndSet boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(false, x, "getAndSet boolean value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, true); + + boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, false); + assertEquals(true, o, "getAndSetAcquire boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(false, x, "getAndSetAcquire boolean value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, true); + + boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, false); + assertEquals(true, o, "getAndSetRelease boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(false, x, "getAndSetRelease boolean value"); + } + // get and bitwise or { @@ -554,7 +580,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(false, false); assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(true, x, "failing weakCompareAndSetRe boolean value"); + assertEquals(true, x, "failing weakCompareAndSet boolean value"); } // Compare set and get @@ -567,7 +593,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(false, x, "getAndSet boolean value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(true); @@ -577,7 +602,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(false, x, "getAndSetAcquire boolean value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(true); @@ -827,10 +851,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, true, false); - assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(false, x, "failing weakCompareAndSetAcquire boolean value"); + assertEquals(false, x, "failing weakCompareAndSetRelease boolean value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java index cd54a8e16d55..514d19eff951 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessByte */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessByte extends VarHandleBaseTest { static final byte static_final_v = (byte)0x01; - static byte static_v; + static byte static_v = (byte)0x01; - final byte final_v = (byte)0x01; + final byte final_v; byte v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessByte extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessByte() { + final_v = (byte)0x01; + v = (byte)0x01; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01); + byte o = (byte) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, (byte)0x23); assertEquals((byte)0x01, o, "getAndSet byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals((byte)0x23, x, "getAndSet byte value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01); + + byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, (byte)0x23); + assertEquals((byte)0x01, o, "getAndSetAcquire byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals((byte)0x23, x, "getAndSetAcquire byte value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01); + + byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, (byte)0x23); + assertEquals((byte)0x01, o, "getAndSetRelease byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals((byte)0x23, x, "getAndSetRelease byte value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01); @@ -576,7 +602,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((byte)0x23, (byte)0x45); assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals((byte)0x01, x, "failing weakCompareAndSetRe byte value"); + assertEquals((byte)0x01, x, "failing weakCompareAndSet byte value"); } // Compare set and get @@ -589,7 +615,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals((byte)0x23, x, "getAndSet byte value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact((byte)0x01); @@ -599,7 +624,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals((byte)0x23, x, "getAndSetAcquire byte value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact((byte)0x01); @@ -871,10 +895,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x01, (byte)0x45); - assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals((byte)0x23, x, "failing weakCompareAndSetAcquire byte value"); + assertEquals((byte)0x23, x, "failing weakCompareAndSetRelease byte value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java index e67de6cf7a44..4642e8196a03 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessChar */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessChar extends VarHandleBaseTest { static final char static_final_v = '\u0123'; - static char static_v; + static char static_v = '\u0123'; - final char final_v = '\u0123'; + final char final_v; char v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessChar extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessChar() { + final_v = '\u0123'; + v = '\u0123'; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123'); + char o = (char) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, '\u4567'); assertEquals('\u0123', o, "getAndSet char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals('\u4567', x, "getAndSet char value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123'); + + char o = (char) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, '\u4567'); + assertEquals('\u0123', o, "getAndSetAcquire char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals('\u4567', x, "getAndSetAcquire char value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123'); + + char o = (char) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, '\u4567'); + assertEquals('\u0123', o, "getAndSetRelease char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals('\u4567', x, "getAndSetRelease char value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123'); @@ -576,7 +602,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact('\u4567', '\u89AB'); assertEquals(success, false, "failing weakCompareAndSet char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals('\u0123', x, "failing weakCompareAndSetRe char value"); + assertEquals('\u0123', x, "failing weakCompareAndSet char value"); } // Compare set and get @@ -589,7 +615,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals('\u4567', x, "getAndSet char value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact('\u0123'); @@ -599,7 +624,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals('\u4567', x, "getAndSetAcquire char value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact('\u0123'); @@ -871,10 +895,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, '\u0123', '\u89AB'); - assertEquals(success, false, "failing weakCompareAndSetAcquire char"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals('\u4567', x, "failing weakCompareAndSetAcquire char value"); + assertEquals('\u4567', x, "failing weakCompareAndSetRelease char value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java index d944c4316c26..b1f88a18ca8f 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessDouble */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessDouble extends VarHandleBaseTest { static final double static_final_v = 1.0d; - static double static_v; + static double static_v = 1.0d; - final double final_v = 1.0d; + final double final_v; double v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessDouble extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessDouble() { + final_v = 1.0d; + v = 1.0d; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handle // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d); + double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0d); assertEquals(1.0d, o, "getAndSet double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(2.0d, x, "getAndSet double value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d); + + double o = (double) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, 2.0d); + assertEquals(1.0d, o, "getAndSetAcquire double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(2.0d, x, "getAndSetAcquire double value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d); + + double o = (double) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, 2.0d); + assertEquals(1.0d, o, "getAndSetRelease double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(2.0d, x, "getAndSetRelease double value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d); @@ -498,7 +524,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0d, 3.0d); assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(1.0d, x, "failing weakCompareAndSetRe double value"); + assertEquals(1.0d, x, "failing weakCompareAndSet double value"); } // Compare set and get @@ -511,7 +537,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(2.0d, x, "getAndSet double value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(1.0d); @@ -521,7 +546,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(2.0d, x, "getAndSetAcquire double value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(1.0d); @@ -715,10 +739,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0d, 3.0d); - assertEquals(success, false, "failing weakCompareAndSetAcquire double"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(2.0d, x, "failing weakCompareAndSetAcquire double value"); + assertEquals(2.0d, x, "failing weakCompareAndSetRelease double value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java index 2b1beed2c013..1836b1729dc3 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessFloat */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessFloat extends VarHandleBaseTest { static final float static_final_v = 1.0f; - static float static_v; + static float static_v = 1.0f; - final float final_v = 1.0f; + final float final_v; float v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessFloat extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessFloat() { + final_v = 1.0f; + v = 1.0f; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f); + float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0f); assertEquals(1.0f, o, "getAndSet float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(2.0f, x, "getAndSet float value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f); + + float o = (float) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, 2.0f); + assertEquals(1.0f, o, "getAndSetAcquire float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(2.0f, x, "getAndSetAcquire float value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f); + + float o = (float) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, 2.0f); + assertEquals(1.0f, o, "getAndSetRelease float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(2.0f, x, "getAndSetRelease float value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f); @@ -498,7 +524,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0f, 3.0f); assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(1.0f, x, "failing weakCompareAndSetRe float value"); + assertEquals(1.0f, x, "failing weakCompareAndSet float value"); } // Compare set and get @@ -511,7 +537,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(2.0f, x, "getAndSet float value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(1.0f); @@ -521,7 +546,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(2.0f, x, "getAndSetAcquire float value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(1.0f); @@ -715,10 +739,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0f, 3.0f); - assertEquals(success, false, "failing weakCompareAndSetAcquire float"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(2.0f, x, "failing weakCompareAndSetAcquire float value"); + assertEquals(2.0f, x, "failing weakCompareAndSetRelease float value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java index 5dc48bc22f97..e260b50267d9 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessInt */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { static final int static_final_v = 0x01234567; - static int static_v; + static int static_v = 0x01234567; - final int final_v = 0x01234567; + final int final_v; int v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessInt() { + final_v = 0x01234567; + v = 0x01234567; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles h // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567); + int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 0x89ABCDEF); assertEquals(0x01234567, o, "getAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(0x89ABCDEF, x, "getAndSet int value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567); + + int o = (int) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, 0x89ABCDEF); + assertEquals(0x01234567, o, "getAndSetAcquire int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(0x89ABCDEF, x, "getAndSetAcquire int value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567); + + int o = (int) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, 0x89ABCDEF); + assertEquals(0x01234567, o, "getAndSetRelease int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(0x89ABCDEF, x, "getAndSetRelease int value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567); @@ -576,7 +602,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0x89ABCDEF, 0xCAFEBABE); assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(0x01234567, x, "failing weakCompareAndSetRe int value"); + assertEquals(0x01234567, x, "failing weakCompareAndSet int value"); } // Compare set and get @@ -589,7 +615,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(0x89ABCDEF, x, "getAndSet int value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(0x01234567); @@ -599,7 +624,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(0x89ABCDEF, x, "getAndSetAcquire int value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(0x01234567); @@ -871,10 +895,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x01234567, 0xCAFEBABE); - assertEquals(success, false, "failing weakCompareAndSetAcquire int"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(0x89ABCDEF, x, "failing weakCompareAndSetAcquire int value"); + assertEquals(0x89ABCDEF, x, "failing weakCompareAndSetRelease int value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java index 0950470c8797..942ad2c38c11 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessLong */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { static final long static_final_v = 0x0123456789ABCDEFL; - static long static_v; + static long static_v = 0x0123456789ABCDEFL; - final long final_v = 0x0123456789ABCDEFL; + final long final_v; long v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessLong() { + final_v = 0x0123456789ABCDEFL; + v = 0x0123456789ABCDEFL; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL); + long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 0xCAFEBABECAFEBABEL); assertEquals(0x0123456789ABCDEFL, o, "getAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(0xCAFEBABECAFEBABEL, x, "getAndSet long value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL); + + long o = (long) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL); + assertEquals(0x0123456789ABCDEFL, o, "getAndSetAcquire long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(0xCAFEBABECAFEBABEL, x, "getAndSetAcquire long value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL); + + long o = (long) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL); + assertEquals(0x0123456789ABCDEFL, o, "getAndSetRelease long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(0xCAFEBABECAFEBABEL, x, "getAndSetRelease long value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL); @@ -576,7 +602,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(0x0123456789ABCDEFL, x, "failing weakCompareAndSetRe long value"); + assertEquals(0x0123456789ABCDEFL, x, "failing weakCompareAndSet long value"); } // Compare set and get @@ -589,7 +615,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(0xCAFEBABECAFEBABEL, x, "getAndSet long value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL); @@ -599,7 +624,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(0xCAFEBABECAFEBABEL, x, "getAndSetAcquire long value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL); @@ -871,10 +895,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); - assertEquals(success, false, "failing weakCompareAndSetAcquire long"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(0xCAFEBABECAFEBABEL, x, "failing weakCompareAndSetAcquire long value"); + assertEquals(0xCAFEBABECAFEBABEL, x, "failing weakCompareAndSetRelease long value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessNullRestrictedValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessNullRestrictedValue.java new file mode 100644 index 000000000000..aeb2d8495941 --- /dev/null +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessNullRestrictedValue.java @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +/* + * @test + * @enablePreview + * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds + * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessNullRestrictedValue + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.List; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class VarHandleTestMethodHandleAccessNullRestrictedValue extends VarHandleBaseTest { + static final @NullRestricted NullRestrictedValue static_final_v = NullRestrictedValue.of((byte)20,(short)1854); + + static @NullRestricted NullRestrictedValue static_v = NullRestrictedValue.of((byte)20,(short)1854); + + final @NullRestricted NullRestrictedValue final_v; + + @NullRestricted NullRestrictedValue v; + + VarHandle vhFinalField; + + VarHandle vhField; + + VarHandle vhStaticField; + + VarHandle vhStaticFinalField; + + VarHandle vhArray; + + public VarHandleTestMethodHandleAccessNullRestrictedValue() { + final_v = NullRestrictedValue.of((byte)20,(short)1854); + v = NullRestrictedValue.of((byte)20,(short)1854); + super(); + } + + @BeforeAll + public void setup() throws Exception { + vhFinalField = MethodHandles.lookup().findVarHandle( + VarHandleTestMethodHandleAccessNullRestrictedValue.class, "final_v", NullRestrictedValue.class); + + vhField = MethodHandles.lookup().findVarHandle( + VarHandleTestMethodHandleAccessNullRestrictedValue.class, "v", NullRestrictedValue.class); + + vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestMethodHandleAccessNullRestrictedValue.class, "static_final_v", NullRestrictedValue.class); + + vhStaticField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestMethodHandleAccessNullRestrictedValue.class, "static_v", NullRestrictedValue.class); + + vhArray = MethodHandles.arrayElementVarHandle(NullRestrictedValue[].class); + } + + public Object[][] accessTestCaseProvider() throws Exception { + List> cases = new ArrayList<>(); + + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { + cases.add(new MethodHandleAccessTestCase("Instance field", + vhField, f, hs -> testInstanceField(this, hs))); + cases.add(new MethodHandleAccessTestCase("Instance field unsupported", + vhField, f, hs -> testInstanceFieldUnsupported(this, hs), + false)); + cases.add(new MethodHandleAccessTestCase("Instance field null pointer exception", + vhField, f, hs -> testInstanceFieldNullPointerException(this, hs), + false)); + + cases.add(new MethodHandleAccessTestCase("Static field", + vhStaticField, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testStaticField)); + cases.add(new MethodHandleAccessTestCase("Static field unsupported", + vhStaticField, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testStaticFieldUnsupported, + false)); + cases.add(new MethodHandleAccessTestCase("Static field null pointer exception", + vhStaticField, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testStaticFieldNullPointerException, + false)); + + cases.add(new MethodHandleAccessTestCase("Array", + vhArray, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testArray)); + cases.add(new MethodHandleAccessTestCase("Array unsupported", + vhArray, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testArrayUnsupported, + false)); + cases.add(new MethodHandleAccessTestCase("Array index out of bounds", + vhArray, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testArrayIndexOutOfBounds, + false)); + cases.add(new MethodHandleAccessTestCase("Array null pointer exception", + vhArray, f, VarHandleTestMethodHandleAccessNullRestrictedValue::testArrayNullPointerException, + false)); + } + + // Work around issue with jtreg summary reporting which truncates + // the String result of Object.toString to 30 characters, hence + // the first dummy argument + return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); + } + + @ParameterizedTest + @MethodSource("accessTestCaseProvider") + public void testAccess(String desc, AccessTestCase atc) throws Throwable { + T t = atc.get(); + int iters = atc.requiresLoop() ? ITERS : 1; + for (int c = 0; c < iters; c++) { + atc.testAccess(t); + } + } + + static void testInstanceField(VarHandleTestMethodHandleAccessNullRestrictedValue recv, Handles hs) throws Throwable { + // Plain + { + hs.get(TestAccessMode.SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "set NullRestrictedValue value"); + } + + + // Volatile + { + hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + hs.get(TestAccessMode.SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + boolean success = false; + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET); + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + hs.get(TestAccessMode.SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + + static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessNullRestrictedValue recv, Handles hs) throws Throwable { + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { + checkUOE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) { + checkUOE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + } + + + static void testStaticField(Handles hs) throws Throwable { + // Plain + { + hs.get(TestAccessMode.SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "set NullRestrictedValue value"); + } + + + // Volatile + { + hs.get(TestAccessMode.SET_VOLATILE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + hs.get(TestAccessMode.SET_RELEASE).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + hs.get(TestAccessMode.SET_OPAQUE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + hs.get(TestAccessMode.SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE); + boolean success = (boolean) mh.invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + hs.get(TestAccessMode.SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + + static void testStaticFieldUnsupported(Handles hs) throws Throwable { + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { + checkUOE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) { + checkUOE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + } + + + static void testArray(Handles hs) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + for (int i = 0; i < array.length; i++) { + // Plain + { + hs.get(TestAccessMode.SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "get NullRestrictedValue value"); + } + + + // Volatile + { + hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setVolatile NullRestrictedValue value"); + } + + // Lazy + { + hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "setRelease NullRestrictedValue value"); + } + + // Opaque + { + hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "setOpaque NullRestrictedValue value"); + } + + hs.get(TestAccessMode.SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + // Compare + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, true, "success compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndSet NullRestrictedValue value"); + } + + { + boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, false, "failing compareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndSet NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchange NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchange NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "success compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "failing compareAndExchangeAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing compareAndExchangeAcquire NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + assertEquals(r, NullRestrictedValue.of((byte)-42,(short)1854), "success compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success compareAndExchangeRelease NullRestrictedValue value"); + } + + { + NullRestrictedValue r = (NullRestrictedValue) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(r, NullRestrictedValue.of((byte)20,(short)1854), "failing compareAndExchangeRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing compareAndExchangeRelease NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetPlain NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetPlain NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSetAcquire NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSetAcquire NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "success weakCompareAndSetRelease NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "failing weakCompareAndSetRelease NullRestrictedValue value"); + } + + { + MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) mh.invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + if (!success) weakDelay(); + } + assertEquals(success, true, "success weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "success weakCompareAndSet NullRestrictedValue"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)-31083)); + assertEquals(success, false, "failing weakCompareAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), x, "failing weakCompareAndSet NullRestrictedValue value"); + } + + // Compare set and get + { + hs.get(TestAccessMode.SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSet NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSet NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetAcquire NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetAcquire NullRestrictedValue value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + + NullRestrictedValue o = (NullRestrictedValue) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, NullRestrictedValue.of((byte)-42,(short)1854)); + assertEquals(NullRestrictedValue.of((byte)20,(short)1854), o, "getAndSetRelease NullRestrictedValue"); + NullRestrictedValue x = (NullRestrictedValue) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(NullRestrictedValue.of((byte)-42,(short)1854), x, "getAndSetRelease NullRestrictedValue value"); + } + + + } + } + + static void testArrayUnsupported(Handles hs) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + final int i = 0; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { + checkUOE(am, () -> { + NullRestrictedValue o = (NullRestrictedValue) hs.get(am).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) { + checkUOE(am, () -> { + NullRestrictedValue o = (NullRestrictedValue) hs.get(am).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + } + + static void testArrayIndexOutOfBounds(Handles hs) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + + for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) { + final int ci = i; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { + checkAIOOBE(am, () -> { + NullRestrictedValue x = (NullRestrictedValue) hs.get(am).invokeExact(array, ci); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkAIOOBE(am, () -> { + hs.get(am).invokeExact(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkAIOOBE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(array, ci, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)-42,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkAIOOBE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(array, ci, NullRestrictedValue.of((byte)-42,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkAIOOBE(am, () -> { + NullRestrictedValue o = (NullRestrictedValue) hs.get(am).invokeExact(array, ci, NullRestrictedValue.of((byte)20,(short)1854)); + }); + } + + + } + } + + static void testInstanceFieldNullPointerException(VarHandleTestMethodHandleAccessNullRestrictedValue recv, Handles hs) throws Throwable { + NullRestrictedValue value = null; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(recv, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(recv, value); + }); + } + } + + static void testStaticFieldNullPointerException(Handles hs) throws Throwable { + NullRestrictedValue value = null; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(value); + }); + } + } + + static void testArrayNullPointerException(Handles hs) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + NullRestrictedValue value = null; + + final int i = 0; + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(array, i, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(array, i, NullRestrictedValue.of((byte)20,(short)1854), value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + NullRestrictedValue r = (NullRestrictedValue) hs.get(am).invokeExact(array, i, value); + }); + } + } +} + diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java index 337367d8147c..5caacdaabc65 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessShort */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessShort extends VarHandleBaseTest { static final short static_final_v = (short)0x0123; - static short static_v; + static short static_v = (short)0x0123; - final short final_v = (short)0x0123; + final short final_v; short v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessShort extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessShort() { + final_v = (short)0x0123; + v = (short)0x0123; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123); + short o = (short) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, (short)0x4567); assertEquals((short)0x0123, o, "getAndSet short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals((short)0x4567, x, "getAndSet short value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123); + + short o = (short) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, (short)0x4567); + assertEquals((short)0x0123, o, "getAndSetAcquire short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals((short)0x4567, x, "getAndSetAcquire short value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123); + + short o = (short) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, (short)0x4567); + assertEquals((short)0x0123, o, "getAndSetRelease short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals((short)0x4567, x, "getAndSetRelease short value"); + } + // get and add, add and get { hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123); @@ -576,7 +602,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((short)0x4567, (short)0x89AB); assertEquals(success, false, "failing weakCompareAndSet short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals((short)0x0123, x, "failing weakCompareAndSetRe short value"); + assertEquals((short)0x0123, x, "failing weakCompareAndSet short value"); } // Compare set and get @@ -589,7 +615,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals((short)0x4567, x, "getAndSet short value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact((short)0x0123); @@ -599,7 +624,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals((short)0x4567, x, "getAndSetAcquire short value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact((short)0x0123); @@ -871,10 +895,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x0123, (short)0x89AB); - assertEquals(success, false, "failing weakCompareAndSetAcquire short"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals((short)0x4567, x, "failing weakCompareAndSetAcquire short value"); + assertEquals((short)0x4567, x, "failing weakCompareAndSetRelease short value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java index 13245291af94..2a3c2b31f852 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ /* * @test - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessString */ @@ -46,9 +46,9 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { static final String static_final_v = "foo"; - static String static_v; + static String static_v = "foo"; - final String final_v = "foo"; + final String final_v; String v; @@ -62,6 +62,12 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessString() { + final_v = "foo"; + v = "foo"; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -288,12 +294,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handle // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, "foo"); + String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar"); assertEquals("foo", o, "getAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals("bar", x, "getAndSet String value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, "foo"); + + String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, "bar"); + assertEquals("foo", o, "getAndSetAcquire String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals("bar", x, "getAndSetAcquire String value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, "foo"); + + String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, "bar"); + assertEquals("foo", o, "getAndSetRelease String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals("bar", x, "getAndSetRelease String value"); + } + } @@ -476,7 +502,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "baz"); assertEquals(success, false, "failing weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals("foo", x, "failing weakCompareAndSetRe String value"); + assertEquals("foo", x, "failing weakCompareAndSet String value"); } // Compare set and get @@ -489,7 +515,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals("bar", x, "getAndSet String value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact("foo"); @@ -499,7 +524,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals("bar", x, "getAndSetAcquire String value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact("foo"); @@ -671,10 +695,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "foo", "baz"); - assertEquals(success, false, "failing weakCompareAndSetAcquire String"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals("bar", x, "failing weakCompareAndSetAcquire String value"); + assertEquals("bar", x, "failing weakCompareAndSetRelease String value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessValue.java index 64cf0326d5f1..e13326927bf7 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessValue.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,9 @@ * @test * @enablePreview * @modules java.base/jdk.internal.vm.annotation - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * java.base/jdk.internal.value + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessValue */ @@ -48,9 +49,9 @@ public class VarHandleTestMethodHandleAccessValue extends VarHandleBaseTest { static final Value static_final_v = Value.getInstance(10); - static Value static_v; + static Value static_v = Value.getInstance(10); - final Value final_v = Value.getInstance(10); + final Value final_v; Value v; @@ -64,6 +65,12 @@ public class VarHandleTestMethodHandleAccessValue extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccessValue() { + final_v = Value.getInstance(10); + v = Value.getInstance(10); + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -290,12 +297,32 @@ static void testInstanceField(VarHandleTestMethodHandleAccessValue recv, Handles // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, Value.getInstance(10)); + Value o = (Value) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, Value.getInstance(20)); assertEquals(Value.getInstance(10), o, "getAndSet Value"); Value x = (Value) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(Value.getInstance(20), x, "getAndSet Value value"); } + { + hs.get(TestAccessMode.SET).invokeExact(recv, Value.getInstance(10)); + + Value o = (Value) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, Value.getInstance(20)); + assertEquals(Value.getInstance(10), o, "getAndSetAcquire Value"); + Value x = (Value) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(Value.getInstance(20), x, "getAndSetAcquire Value value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, Value.getInstance(10)); + + Value o = (Value) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, Value.getInstance(20)); + assertEquals(Value.getInstance(10), o, "getAndSetRelease Value"); + Value x = (Value) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(Value.getInstance(20), x, "getAndSetRelease Value value"); + } + } @@ -478,7 +505,7 @@ static void testStaticField(Handles hs) throws Throwable { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(Value.getInstance(20), Value.getInstance(30)); assertEquals(success, false, "failing weakCompareAndSet Value"); Value x = (Value) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(Value.getInstance(10), x, "failing weakCompareAndSetRe Value value"); + assertEquals(Value.getInstance(10), x, "failing weakCompareAndSet Value value"); } // Compare set and get @@ -491,7 +518,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(Value.getInstance(20), x, "getAndSet Value value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(Value.getInstance(10)); @@ -501,7 +527,6 @@ static void testStaticField(Handles hs) throws Throwable { assertEquals(Value.getInstance(20), x, "getAndSetAcquire Value value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact(Value.getInstance(10)); @@ -673,10 +698,10 @@ static void testArray(Handles hs) throws Throwable { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, Value.getInstance(10), Value.getInstance(30)); - assertEquals(success, false, "failing weakCompareAndSetAcquire Value"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, Value.getInstance(10), Value.getInstance(30)); + assertEquals(success, false, "failing weakCompareAndSetRelease Value"); Value x = (Value) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(Value.getInstance(20), x, "failing weakCompareAndSetAcquire Value value"); + assertEquals(Value.getInstance(20), x, "failing weakCompareAndSetRelease Value value"); } { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java index a413029d87d6..27a4eef9ad2a 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { static boolean static_v = true; - final boolean final_v = true; + final boolean final_v; - boolean v = true; + boolean v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeBoolean() { + final_v = true; + v = true; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // actual reference class boolean x = (boolean) vh.compareAndExchange(recv, true, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.compareAndExchange(0, true, true); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // actual reference class boolean x = (boolean) vh.compareAndExchangeAcquire(recv, true, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.compareAndExchangeAcquire(0, true, true); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // actual reference class boolean x = (boolean) vh.compareAndExchangeRelease(recv, true, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.compareAndExchangeRelease(0, true, true); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndSet(0, true); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndSetAcquire(0, true); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndSetRelease(0, true); }); // Incorrect return type @@ -655,7 +661,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseOr(0, true); }); // Incorrect return type @@ -685,7 +691,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseOrAcquire(0, true); }); // Incorrect return type @@ -710,27 +716,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) vh.getAndBitwiseOrRelease(null, true); }); checkCCE(() -> { // receiver reference class - boolean x = (boolean) vh.getAndBitwiseOr(Void.class, true); + boolean x = (boolean) vh.getAndBitwiseOrRelease(Void.class, true); }); checkWMTE(() -> { // value reference class - boolean x = (boolean) vh.getAndBitwiseOr(recv, Void.class); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - boolean x = (boolean) vh.getAndBitwiseOr(0, true); + checkWMTE(() -> { // receiver primitive class + boolean x = (boolean) vh.getAndBitwiseOrRelease(0, true); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, true); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, true); }); checkWMTE(() -> { // primitive class - int x = (int) vh.getAndBitwiseOr(recv, true); + int x = (int) vh.getAndBitwiseOrRelease(recv, true); }); // Incorrect arity checkWMTE(() -> { // 0 - boolean x = (boolean) vh.getAndBitwiseOr(); + boolean x = (boolean) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - boolean x = (boolean) vh.getAndBitwiseOr(recv, true, Void.class); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, true, Void.class); }); @@ -745,7 +751,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseAnd(0, true); }); // Incorrect return type @@ -775,7 +781,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseAndAcquire(0, true); }); // Incorrect return type @@ -800,27 +806,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) vh.getAndBitwiseAndRelease(null, true); }); checkCCE(() -> { // receiver reference class - boolean x = (boolean) vh.getAndBitwiseAnd(Void.class, true); + boolean x = (boolean) vh.getAndBitwiseAndRelease(Void.class, true); }); checkWMTE(() -> { // value reference class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, Void.class); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(0, true); + checkWMTE(() -> { // receiver primitive class + boolean x = (boolean) vh.getAndBitwiseAndRelease(0, true); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, true); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, true); }); checkWMTE(() -> { // primitive class - int x = (int) vh.getAndBitwiseAnd(recv, true); + int x = (int) vh.getAndBitwiseAndRelease(recv, true); }); // Incorrect arity checkWMTE(() -> { // 0 - boolean x = (boolean) vh.getAndBitwiseAnd(); + boolean x = (boolean) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - boolean x = (boolean) vh.getAndBitwiseAnd(recv, true, Void.class); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, true, Void.class); }); @@ -835,7 +841,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseXor(0, true); }); // Incorrect return type @@ -865,7 +871,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) vh.getAndBitwiseXorAcquire(0, true); }); // Incorrect return type @@ -890,27 +896,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) vh.getAndBitwiseXorRelease(null, true); }); checkCCE(() -> { // receiver reference class - boolean x = (boolean) vh.getAndBitwiseXor(Void.class, true); + boolean x = (boolean) vh.getAndBitwiseXorRelease(Void.class, true); }); checkWMTE(() -> { // value reference class - boolean x = (boolean) vh.getAndBitwiseXor(recv, Void.class); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - boolean x = (boolean) vh.getAndBitwiseXor(0, true); + checkWMTE(() -> { // receiver primitive class + boolean x = (boolean) vh.getAndBitwiseXorRelease(0, true); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, true); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, true); }); checkWMTE(() -> { // primitive class - int x = (int) vh.getAndBitwiseXor(recv, true); + int x = (int) vh.getAndBitwiseXorRelease(recv, true); }); // Incorrect arity checkWMTE(() -> { // 0 - boolean x = (boolean) vh.getAndBitwiseXor(); + boolean x = (boolean) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - boolean x = (boolean) vh.getAndBitwiseXor(recv, true, Void.class); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, true, Void.class); }); } @@ -1028,7 +1034,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)). invokeExact(recv, true, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class , boolean.class, boolean.class)). invokeExact(0, true, true); }); @@ -1065,7 +1071,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, boolean.class)). invokeExact(0, true); }); @@ -1103,7 +1109,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, boolean.class)). invokeExact(0, true); }); @@ -1501,7 +1507,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseOrRelease(Void.class); @@ -1564,7 +1570,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseAndRelease(Void.class); @@ -1627,7 +1633,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndBitwiseXorRelease(Void.class); @@ -2281,7 +2287,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class boolean x = (boolean) vh.getAndSet(0, 0, true); }); checkWMTE(() -> { // index reference class @@ -2314,7 +2320,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class boolean x = (boolean) vh.getAndSetAcquire(0, 0, true); }); checkWMTE(() -> { // index reference class @@ -2347,7 +2353,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class boolean x = (boolean) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class boolean x = (boolean) vh.getAndSetRelease(0, 0, true); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java index 40ce205ecb7b..64036c334898 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { static byte static_v = (byte)0x01; - final byte final_v = (byte)0x01; + final byte final_v; - byte v = (byte)0x01; + byte v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeByte() { + final_v = (byte)0x01; + v = (byte)0x01; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // actual reference class byte x = (byte) vh.compareAndExchange(recv, (byte)0x01, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.compareAndExchange(0, (byte)0x01, (byte)0x01); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // actual reference class byte x = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.compareAndExchangeAcquire(0, (byte)0x01, (byte)0x01); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // actual reference class byte x = (byte) vh.compareAndExchangeRelease(recv, (byte)0x01, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.compareAndExchangeRelease(0, (byte)0x01, (byte)0x01); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndSet(0, (byte)0x01); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndSetAcquire(0, (byte)0x01); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndSetRelease(0, (byte)0x01); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndAdd(0, (byte)0x01); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndAddAcquire(0, (byte)0x01); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndAddRelease(0, (byte)0x01); }); // Incorrect return type @@ -741,7 +747,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseOr(0, (byte)0x01); }); // Incorrect return type @@ -771,7 +777,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseOrAcquire(0, (byte)0x01); }); // Incorrect return type @@ -796,27 +802,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V byte x = (byte) vh.getAndBitwiseOrRelease(null, (byte)0x01); }); checkCCE(() -> { // receiver reference class - byte x = (byte) vh.getAndBitwiseOr(Void.class, (byte)0x01); + byte x = (byte) vh.getAndBitwiseOrRelease(Void.class, (byte)0x01); }); checkWMTE(() -> { // value reference class - byte x = (byte) vh.getAndBitwiseOr(recv, Void.class); + byte x = (byte) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - byte x = (byte) vh.getAndBitwiseOr(0, (byte)0x01); + checkWMTE(() -> { // receiver primitive class + byte x = (byte) vh.getAndBitwiseOrRelease(0, (byte)0x01); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, (byte)0x01); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, (byte)0x01); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseOr(recv, (byte)0x01); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, (byte)0x01); }); // Incorrect arity checkWMTE(() -> { // 0 - byte x = (byte) vh.getAndBitwiseOr(); + byte x = (byte) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - byte x = (byte) vh.getAndBitwiseOr(recv, (byte)0x01, Void.class); + byte x = (byte) vh.getAndBitwiseOrRelease(recv, (byte)0x01, Void.class); }); @@ -831,7 +837,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseAnd(0, (byte)0x01); }); // Incorrect return type @@ -861,7 +867,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseAndAcquire(0, (byte)0x01); }); // Incorrect return type @@ -886,27 +892,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V byte x = (byte) vh.getAndBitwiseAndRelease(null, (byte)0x01); }); checkCCE(() -> { // receiver reference class - byte x = (byte) vh.getAndBitwiseAnd(Void.class, (byte)0x01); + byte x = (byte) vh.getAndBitwiseAndRelease(Void.class, (byte)0x01); }); checkWMTE(() -> { // value reference class - byte x = (byte) vh.getAndBitwiseAnd(recv, Void.class); + byte x = (byte) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - byte x = (byte) vh.getAndBitwiseAnd(0, (byte)0x01); + checkWMTE(() -> { // receiver primitive class + byte x = (byte) vh.getAndBitwiseAndRelease(0, (byte)0x01); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, (byte)0x01); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, (byte)0x01); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, (byte)0x01); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, (byte)0x01); }); // Incorrect arity checkWMTE(() -> { // 0 - byte x = (byte) vh.getAndBitwiseAnd(); + byte x = (byte) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - byte x = (byte) vh.getAndBitwiseAnd(recv, (byte)0x01, Void.class); + byte x = (byte) vh.getAndBitwiseAndRelease(recv, (byte)0x01, Void.class); }); @@ -921,7 +927,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseXor(0, (byte)0x01); }); // Incorrect return type @@ -951,7 +957,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) vh.getAndBitwiseXorAcquire(0, (byte)0x01); }); // Incorrect return type @@ -976,27 +982,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, V byte x = (byte) vh.getAndBitwiseXorRelease(null, (byte)0x01); }); checkCCE(() -> { // receiver reference class - byte x = (byte) vh.getAndBitwiseXor(Void.class, (byte)0x01); + byte x = (byte) vh.getAndBitwiseXorRelease(Void.class, (byte)0x01); }); checkWMTE(() -> { // value reference class - byte x = (byte) vh.getAndBitwiseXor(recv, Void.class); + byte x = (byte) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - byte x = (byte) vh.getAndBitwiseXor(0, (byte)0x01); + checkWMTE(() -> { // receiver primitive class + byte x = (byte) vh.getAndBitwiseXorRelease(0, (byte)0x01); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, (byte)0x01); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, (byte)0x01); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseXor(recv, (byte)0x01); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, (byte)0x01); }); // Incorrect arity checkWMTE(() -> { // 0 - byte x = (byte) vh.getAndBitwiseXor(); + byte x = (byte) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - byte x = (byte) vh.getAndBitwiseXor(recv, (byte)0x01, Void.class); + byte x = (byte) vh.getAndBitwiseXorRelease(recv, (byte)0x01, Void.class); }); } @@ -1114,7 +1120,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, H byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)). invokeExact(recv, (byte)0x01, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class , byte.class, byte.class)). invokeExact(0, (byte)0x01, (byte)0x01); }); @@ -1151,7 +1157,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, H byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)). invokeExact(0, (byte)0x01); }); @@ -1188,7 +1194,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, H byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)). invokeExact(0, (byte)0x01); }); @@ -1225,7 +1231,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, H byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)). invokeExact(0, (byte)0x01); }); @@ -1684,7 +1690,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseOrRelease(Void.class); @@ -1747,7 +1753,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseAndRelease(Void.class); @@ -1810,7 +1816,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndBitwiseXorRelease(Void.class); @@ -2489,7 +2495,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class byte x = (byte) vh.getAndSet(0, 0, (byte)0x01); }); checkWMTE(() -> { // index reference class @@ -2522,7 +2528,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class byte x = (byte) vh.getAndSetAcquire(0, 0, (byte)0x01); }); checkWMTE(() -> { // index reference class @@ -2555,7 +2561,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class byte x = (byte) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class byte x = (byte) vh.getAndSetRelease(0, 0, (byte)0x01); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java index eb4d91692fd8..b20d86185bf2 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { static char static_v = '\u0123'; - final char final_v = '\u0123'; + final char final_v; - char v = '\u0123'; + char v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeChar() { + final_v = '\u0123'; + v = '\u0123'; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // actual reference class char x = (char) vh.compareAndExchange(recv, '\u0123', Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.compareAndExchange(0, '\u0123', '\u0123'); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // actual reference class char x = (char) vh.compareAndExchangeAcquire(recv, '\u0123', Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.compareAndExchangeAcquire(0, '\u0123', '\u0123'); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // actual reference class char x = (char) vh.compareAndExchangeRelease(recv, '\u0123', Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.compareAndExchangeRelease(0, '\u0123', '\u0123'); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndSet(0, '\u0123'); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndSetAcquire(0, '\u0123'); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndSetRelease(0, '\u0123'); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndAdd(0, '\u0123'); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndAddAcquire(0, '\u0123'); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndAddRelease(0, '\u0123'); }); // Incorrect return type @@ -741,7 +747,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseOr(0, '\u0123'); }); // Incorrect return type @@ -771,7 +777,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseOrAcquire(0, '\u0123'); }); // Incorrect return type @@ -796,27 +802,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V char x = (char) vh.getAndBitwiseOrRelease(null, '\u0123'); }); checkCCE(() -> { // receiver reference class - char x = (char) vh.getAndBitwiseOr(Void.class, '\u0123'); + char x = (char) vh.getAndBitwiseOrRelease(Void.class, '\u0123'); }); checkWMTE(() -> { // value reference class - char x = (char) vh.getAndBitwiseOr(recv, Void.class); + char x = (char) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - char x = (char) vh.getAndBitwiseOr(0, '\u0123'); + checkWMTE(() -> { // receiver primitive class + char x = (char) vh.getAndBitwiseOrRelease(0, '\u0123'); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, '\u0123'); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, '\u0123'); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseOr(recv, '\u0123'); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, '\u0123'); }); // Incorrect arity checkWMTE(() -> { // 0 - char x = (char) vh.getAndBitwiseOr(); + char x = (char) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - char x = (char) vh.getAndBitwiseOr(recv, '\u0123', Void.class); + char x = (char) vh.getAndBitwiseOrRelease(recv, '\u0123', Void.class); }); @@ -831,7 +837,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseAnd(0, '\u0123'); }); // Incorrect return type @@ -861,7 +867,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseAndAcquire(0, '\u0123'); }); // Incorrect return type @@ -886,27 +892,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V char x = (char) vh.getAndBitwiseAndRelease(null, '\u0123'); }); checkCCE(() -> { // receiver reference class - char x = (char) vh.getAndBitwiseAnd(Void.class, '\u0123'); + char x = (char) vh.getAndBitwiseAndRelease(Void.class, '\u0123'); }); checkWMTE(() -> { // value reference class - char x = (char) vh.getAndBitwiseAnd(recv, Void.class); + char x = (char) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - char x = (char) vh.getAndBitwiseAnd(0, '\u0123'); + checkWMTE(() -> { // receiver primitive class + char x = (char) vh.getAndBitwiseAndRelease(0, '\u0123'); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, '\u0123'); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, '\u0123'); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, '\u0123'); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, '\u0123'); }); // Incorrect arity checkWMTE(() -> { // 0 - char x = (char) vh.getAndBitwiseAnd(); + char x = (char) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - char x = (char) vh.getAndBitwiseAnd(recv, '\u0123', Void.class); + char x = (char) vh.getAndBitwiseAndRelease(recv, '\u0123', Void.class); }); @@ -921,7 +927,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseXor(0, '\u0123'); }); // Incorrect return type @@ -951,7 +957,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) vh.getAndBitwiseXorAcquire(0, '\u0123'); }); // Incorrect return type @@ -976,27 +982,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, V char x = (char) vh.getAndBitwiseXorRelease(null, '\u0123'); }); checkCCE(() -> { // receiver reference class - char x = (char) vh.getAndBitwiseXor(Void.class, '\u0123'); + char x = (char) vh.getAndBitwiseXorRelease(Void.class, '\u0123'); }); checkWMTE(() -> { // value reference class - char x = (char) vh.getAndBitwiseXor(recv, Void.class); + char x = (char) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - char x = (char) vh.getAndBitwiseXor(0, '\u0123'); + checkWMTE(() -> { // receiver primitive class + char x = (char) vh.getAndBitwiseXorRelease(0, '\u0123'); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, '\u0123'); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, '\u0123'); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseXor(recv, '\u0123'); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, '\u0123'); }); // Incorrect arity checkWMTE(() -> { // 0 - char x = (char) vh.getAndBitwiseXor(); + char x = (char) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - char x = (char) vh.getAndBitwiseXor(recv, '\u0123', Void.class); + char x = (char) vh.getAndBitwiseXorRelease(recv, '\u0123', Void.class); }); } @@ -1114,7 +1120,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, H char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)). invokeExact(recv, '\u0123', Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) hs.get(am, methodType(char.class, int.class , char.class, char.class)). invokeExact(0, '\u0123', '\u0123'); }); @@ -1151,7 +1157,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, H char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) hs.get(am, methodType(char.class, int.class, char.class)). invokeExact(0, '\u0123'); }); @@ -1188,7 +1194,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, H char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) hs.get(am, methodType(char.class, int.class, char.class)). invokeExact(0, '\u0123'); }); @@ -1225,7 +1231,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, H char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class char x = (char) hs.get(am, methodType(char.class, int.class, char.class)). invokeExact(0, '\u0123'); }); @@ -1684,7 +1690,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseOrRelease(Void.class); @@ -1747,7 +1753,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseAndRelease(Void.class); @@ -1810,7 +1816,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class char x = (char) vh.getAndBitwiseXorRelease(Void.class); @@ -2489,7 +2495,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class char x = (char) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class char x = (char) vh.getAndSet(0, 0, '\u0123'); }); checkWMTE(() -> { // index reference class @@ -2522,7 +2528,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class char x = (char) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class char x = (char) vh.getAndSetAcquire(0, 0, '\u0123'); }); checkWMTE(() -> { // index reference class @@ -2555,7 +2561,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class char x = (char) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class char x = (char) vh.getAndSetRelease(0, 0, '\u0123'); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java index c6687ce08c33..75cc8fab5cba 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { static double static_v = 1.0d; - final double final_v = 1.0d; + final double final_v; - double v = 1.0d; + double v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeDouble() { + final_v = 1.0d; + v = 1.0d; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // actual reference class double x = (double) vh.compareAndExchange(recv, 1.0d, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.compareAndExchange(0, 1.0d, 1.0d); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // actual reference class double x = (double) vh.compareAndExchangeAcquire(recv, 1.0d, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.compareAndExchangeAcquire(0, 1.0d, 1.0d); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // actual reference class double x = (double) vh.compareAndExchangeRelease(recv, 1.0d, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.compareAndExchangeRelease(0, 1.0d, 1.0d); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndSet(0, 1.0d); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndSetAcquire(0, 1.0d); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndSetRelease(0, 1.0d); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndAdd(0, 1.0d); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndAddAcquire(0, 1.0d); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, checkWMTE(() -> { // value reference class double x = (double) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) vh.getAndAddRelease(0, 1.0d); }); // Incorrect return type @@ -846,7 +852,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)). invokeExact(recv, 1.0d, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) hs.get(am, methodType(double.class, int.class , double.class, double.class)). invokeExact(0, 1.0d, 1.0d); }); @@ -883,7 +889,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) hs.get(am, methodType(double.class, int.class, double.class)). invokeExact(0, 1.0d); }); @@ -920,7 +926,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class double x = (double) hs.get(am, methodType(double.class, int.class, double.class)). invokeExact(0, 1.0d); }); @@ -1973,7 +1979,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class double x = (double) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class double x = (double) vh.getAndSet(0, 0, 1.0d); }); checkWMTE(() -> { // index reference class @@ -2006,7 +2012,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class double x = (double) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class double x = (double) vh.getAndSetAcquire(0, 0, 1.0d); }); checkWMTE(() -> { // index reference class @@ -2039,7 +2045,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class double x = (double) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class double x = (double) vh.getAndSetRelease(0, 0, 1.0d); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java index 35f0601a9eed..db786f136729 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { static float static_v = 1.0f; - final float final_v = 1.0f; + final float final_v; - float v = 1.0f; + float v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeFloat() { + final_v = 1.0f; + v = 1.0f; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // actual reference class float x = (float) vh.compareAndExchange(recv, 1.0f, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.compareAndExchange(0, 1.0f, 1.0f); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // actual reference class float x = (float) vh.compareAndExchangeAcquire(recv, 1.0f, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.compareAndExchangeAcquire(0, 1.0f, 1.0f); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // actual reference class float x = (float) vh.compareAndExchangeRelease(recv, 1.0f, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.compareAndExchangeRelease(0, 1.0f, 1.0f); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndSet(0, 1.0f); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndSetAcquire(0, 1.0f); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndSetRelease(0, 1.0f); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndAdd(0, 1.0f); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndAddAcquire(0, 1.0f); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, checkWMTE(() -> { // value reference class float x = (float) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) vh.getAndAddRelease(0, 1.0f); }); // Incorrect return type @@ -846,7 +852,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)). invokeExact(recv, 1.0f, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) hs.get(am, methodType(float.class, int.class , float.class, float.class)). invokeExact(0, 1.0f, 1.0f); }); @@ -883,7 +889,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) hs.get(am, methodType(float.class, int.class, float.class)). invokeExact(0, 1.0f); }); @@ -920,7 +926,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class float x = (float) hs.get(am, methodType(float.class, int.class, float.class)). invokeExact(0, 1.0f); }); @@ -1973,7 +1979,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class float x = (float) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class float x = (float) vh.getAndSet(0, 0, 1.0f); }); checkWMTE(() -> { // index reference class @@ -2006,7 +2012,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class float x = (float) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class float x = (float) vh.getAndSetAcquire(0, 0, 1.0f); }); checkWMTE(() -> { // index reference class @@ -2039,7 +2045,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class float x = (float) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class float x = (float) vh.getAndSetRelease(0, 0, 1.0f); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java index 28e3be315829..09fc9c005241 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { static int static_v = 0x01234567; - final int final_v = 0x01234567; + final int final_v; - int v = 0x01234567; + int v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeInt() { + final_v = 0x01234567; + v = 0x01234567; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // actual reference class int x = (int) vh.compareAndExchange(recv, 0x01234567, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.compareAndExchange(0, 0x01234567, 0x01234567); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // actual reference class int x = (int) vh.compareAndExchangeAcquire(recv, 0x01234567, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.compareAndExchangeAcquire(0, 0x01234567, 0x01234567); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // actual reference class int x = (int) vh.compareAndExchangeRelease(recv, 0x01234567, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.compareAndExchangeRelease(0, 0x01234567, 0x01234567); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndSet(0, 0x01234567); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndSetAcquire(0, 0x01234567); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndSetRelease(0, 0x01234567); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndAdd(0, 0x01234567); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndAddAcquire(0, 0x01234567); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndAddRelease(0, 0x01234567); }); // Incorrect return type @@ -741,7 +747,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseOr(0, 0x01234567); }); // Incorrect return type @@ -771,7 +777,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseOrAcquire(0, 0x01234567); }); // Incorrect return type @@ -796,27 +802,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va int x = (int) vh.getAndBitwiseOrRelease(null, 0x01234567); }); checkCCE(() -> { // receiver reference class - int x = (int) vh.getAndBitwiseOr(Void.class, 0x01234567); + int x = (int) vh.getAndBitwiseOrRelease(Void.class, 0x01234567); }); checkWMTE(() -> { // value reference class - int x = (int) vh.getAndBitwiseOr(recv, Void.class); + int x = (int) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - int x = (int) vh.getAndBitwiseOr(0, 0x01234567); + checkWMTE(() -> { // receiver primitive class + int x = (int) vh.getAndBitwiseOrRelease(0, 0x01234567); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, 0x01234567); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, 0x01234567); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x01234567); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, 0x01234567); }); // Incorrect arity checkWMTE(() -> { // 0 - int x = (int) vh.getAndBitwiseOr(); + int x = (int) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - int x = (int) vh.getAndBitwiseOr(recv, 0x01234567, Void.class); + int x = (int) vh.getAndBitwiseOrRelease(recv, 0x01234567, Void.class); }); @@ -831,7 +837,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseAnd(0, 0x01234567); }); // Incorrect return type @@ -861,7 +867,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseAndAcquire(0, 0x01234567); }); // Incorrect return type @@ -886,27 +892,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va int x = (int) vh.getAndBitwiseAndRelease(null, 0x01234567); }); checkCCE(() -> { // receiver reference class - int x = (int) vh.getAndBitwiseAnd(Void.class, 0x01234567); + int x = (int) vh.getAndBitwiseAndRelease(Void.class, 0x01234567); }); checkWMTE(() -> { // value reference class - int x = (int) vh.getAndBitwiseAnd(recv, Void.class); + int x = (int) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - int x = (int) vh.getAndBitwiseAnd(0, 0x01234567); + checkWMTE(() -> { // receiver primitive class + int x = (int) vh.getAndBitwiseAndRelease(0, 0x01234567); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, 0x01234567); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, 0x01234567); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x01234567); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, 0x01234567); }); // Incorrect arity checkWMTE(() -> { // 0 - int x = (int) vh.getAndBitwiseAnd(); + int x = (int) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - int x = (int) vh.getAndBitwiseAnd(recv, 0x01234567, Void.class); + int x = (int) vh.getAndBitwiseAndRelease(recv, 0x01234567, Void.class); }); @@ -921,7 +927,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseXor(0, 0x01234567); }); // Incorrect return type @@ -951,7 +957,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) vh.getAndBitwiseXorAcquire(0, 0x01234567); }); // Incorrect return type @@ -976,27 +982,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Va int x = (int) vh.getAndBitwiseXorRelease(null, 0x01234567); }); checkCCE(() -> { // receiver reference class - int x = (int) vh.getAndBitwiseXor(Void.class, 0x01234567); + int x = (int) vh.getAndBitwiseXorRelease(Void.class, 0x01234567); }); checkWMTE(() -> { // value reference class - int x = (int) vh.getAndBitwiseXor(recv, Void.class); + int x = (int) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - int x = (int) vh.getAndBitwiseXor(0, 0x01234567); + checkWMTE(() -> { // receiver primitive class + int x = (int) vh.getAndBitwiseXorRelease(0, 0x01234567); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, 0x01234567); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, 0x01234567); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x01234567); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, 0x01234567); }); // Incorrect arity checkWMTE(() -> { // 0 - int x = (int) vh.getAndBitwiseXor(); + int x = (int) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - int x = (int) vh.getAndBitwiseXor(recv, 0x01234567, Void.class); + int x = (int) vh.getAndBitwiseXorRelease(recv, 0x01234567, Void.class); }); } @@ -1114,7 +1120,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Ha int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)). invokeExact(recv, 0x01234567, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) hs.get(am, methodType(int.class, int.class , int.class, int.class)). invokeExact(0, 0x01234567, 0x01234567); }); @@ -1151,7 +1157,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Ha int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). invokeExact(0, 0x01234567); }); @@ -1188,7 +1194,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Ha int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). invokeExact(0, 0x01234567); }); @@ -1225,7 +1231,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Ha int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). invokeExact(0, 0x01234567); }); @@ -1684,7 +1690,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseOrRelease(Void.class); @@ -1747,7 +1753,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseAndRelease(Void.class); @@ -1810,7 +1816,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class int x = (int) vh.getAndBitwiseXorRelease(Void.class); @@ -2489,7 +2495,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class int x = (int) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class int x = (int) vh.getAndSet(0, 0, 0x01234567); }); checkWMTE(() -> { // index reference class @@ -2522,7 +2528,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class int x = (int) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class int x = (int) vh.getAndSetAcquire(0, 0, 0x01234567); }); checkWMTE(() -> { // index reference class @@ -2555,7 +2561,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class int x = (int) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class int x = (int) vh.getAndSetRelease(0, 0, 0x01234567); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java index 69c6ee4c6925..017735f10888 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { static long static_v = 0x0123456789ABCDEFL; - final long final_v = 0x0123456789ABCDEFL; + final long final_v; - long v = 0x0123456789ABCDEFL; + long v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeLong() { + final_v = 0x0123456789ABCDEFL; + v = 0x0123456789ABCDEFL; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // actual reference class long x = (long) vh.compareAndExchange(recv, 0x0123456789ABCDEFL, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.compareAndExchange(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // actual reference class long x = (long) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.compareAndExchangeAcquire(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // actual reference class long x = (long) vh.compareAndExchangeRelease(recv, 0x0123456789ABCDEFL, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.compareAndExchangeRelease(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndSet(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndSetAcquire(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndSetRelease(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndAdd(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndAddAcquire(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndAddRelease(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -741,7 +747,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseOr(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -771,7 +777,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseOrAcquire(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -796,27 +802,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V long x = (long) vh.getAndBitwiseOrRelease(null, 0x0123456789ABCDEFL); }); checkCCE(() -> { // receiver reference class - long x = (long) vh.getAndBitwiseOr(Void.class, 0x0123456789ABCDEFL); + long x = (long) vh.getAndBitwiseOrRelease(Void.class, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // value reference class - long x = (long) vh.getAndBitwiseOr(recv, Void.class); + long x = (long) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - long x = (long) vh.getAndBitwiseOr(0, 0x0123456789ABCDEFL); + checkWMTE(() -> { // receiver primitive class + long x = (long) vh.getAndBitwiseOrRelease(0, 0x0123456789ABCDEFL); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, 0x0123456789ABCDEFL); }); // Incorrect arity checkWMTE(() -> { // 0 - long x = (long) vh.getAndBitwiseOr(); + long x = (long) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - long x = (long) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL, Void.class); + long x = (long) vh.getAndBitwiseOrRelease(recv, 0x0123456789ABCDEFL, Void.class); }); @@ -831,7 +837,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseAnd(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -861,7 +867,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseAndAcquire(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -886,27 +892,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V long x = (long) vh.getAndBitwiseAndRelease(null, 0x0123456789ABCDEFL); }); checkCCE(() -> { // receiver reference class - long x = (long) vh.getAndBitwiseAnd(Void.class, 0x0123456789ABCDEFL); + long x = (long) vh.getAndBitwiseAndRelease(Void.class, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // value reference class - long x = (long) vh.getAndBitwiseAnd(recv, Void.class); + long x = (long) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - long x = (long) vh.getAndBitwiseAnd(0, 0x0123456789ABCDEFL); + checkWMTE(() -> { // receiver primitive class + long x = (long) vh.getAndBitwiseAndRelease(0, 0x0123456789ABCDEFL); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, 0x0123456789ABCDEFL); }); // Incorrect arity checkWMTE(() -> { // 0 - long x = (long) vh.getAndBitwiseAnd(); + long x = (long) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - long x = (long) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL, Void.class); + long x = (long) vh.getAndBitwiseAndRelease(recv, 0x0123456789ABCDEFL, Void.class); }); @@ -921,7 +927,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseXor(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -951,7 +957,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) vh.getAndBitwiseXorAcquire(0, 0x0123456789ABCDEFL); }); // Incorrect return type @@ -976,27 +982,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, V long x = (long) vh.getAndBitwiseXorRelease(null, 0x0123456789ABCDEFL); }); checkCCE(() -> { // receiver reference class - long x = (long) vh.getAndBitwiseXor(Void.class, 0x0123456789ABCDEFL); + long x = (long) vh.getAndBitwiseXorRelease(Void.class, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // value reference class - long x = (long) vh.getAndBitwiseXor(recv, Void.class); + long x = (long) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - long x = (long) vh.getAndBitwiseXor(0, 0x0123456789ABCDEFL); + checkWMTE(() -> { // receiver primitive class + long x = (long) vh.getAndBitwiseXorRelease(0, 0x0123456789ABCDEFL); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, 0x0123456789ABCDEFL); }); // Incorrect arity checkWMTE(() -> { // 0 - long x = (long) vh.getAndBitwiseXor(); + long x = (long) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - long x = (long) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL, Void.class); + long x = (long) vh.getAndBitwiseXorRelease(recv, 0x0123456789ABCDEFL, Void.class); }); } @@ -1114,7 +1120,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, H long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)). invokeExact(recv, 0x0123456789ABCDEFL, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) hs.get(am, methodType(long.class, int.class , long.class, long.class)). invokeExact(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL); }); @@ -1151,7 +1157,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, H long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) hs.get(am, methodType(long.class, int.class, long.class)). invokeExact(0, 0x0123456789ABCDEFL); }); @@ -1188,7 +1194,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, H long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) hs.get(am, methodType(long.class, int.class, long.class)). invokeExact(0, 0x0123456789ABCDEFL); }); @@ -1225,7 +1231,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, H long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class long x = (long) hs.get(am, methodType(long.class, int.class, long.class)). invokeExact(0, 0x0123456789ABCDEFL); }); @@ -1684,7 +1690,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseOrRelease(Void.class); @@ -1747,7 +1753,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseAndRelease(Void.class); @@ -1810,7 +1816,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class long x = (long) vh.getAndBitwiseXorRelease(Void.class); @@ -2489,7 +2495,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class long x = (long) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class long x = (long) vh.getAndSet(0, 0, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // index reference class @@ -2522,7 +2528,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class long x = (long) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class long x = (long) vh.getAndSetAcquire(0, 0, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // index reference class @@ -2555,7 +2561,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class long x = (long) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class long x = (long) vh.getAndSetRelease(0, 0, 0x0123456789ABCDEFL); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeNullRestrictedValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeNullRestrictedValue.java new file mode 100644 index 000000000000..9eb6af4baef4 --- /dev/null +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeNullRestrictedValue.java @@ -0,0 +1,2071 @@ +/* + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +/* + * @test + * @bug 8156486 + * @enablePreview + * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value + * @run junit/othervm VarHandleTestMethodTypeNullRestrictedValue + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true VarHandleTestMethodTypeNullRestrictedValue + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false VarHandleTestMethodTypeNullRestrictedValue + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true VarHandleTestMethodTypeNullRestrictedValue + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static java.lang.invoke.MethodType.*; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class VarHandleTestMethodTypeNullRestrictedValue extends VarHandleBaseTest { + static final @NullRestricted NullRestrictedValue static_final_v = NullRestrictedValue.of((byte)20,(short)1854); + + static @NullRestricted NullRestrictedValue static_v = NullRestrictedValue.of((byte)20,(short)1854); + + final @NullRestricted NullRestrictedValue final_v; + + @NullRestricted NullRestrictedValue v; + + VarHandle vhFinalField; + + VarHandle vhField; + + VarHandle vhStaticField; + + VarHandle vhStaticFinalField; + + VarHandle vhArray; + + public VarHandleTestMethodTypeNullRestrictedValue() { + final_v = NullRestrictedValue.of((byte)20,(short)1854); + v = NullRestrictedValue.of((byte)20,(short)1854); + super(); + } + + @BeforeAll + public void setup() throws Exception { + vhFinalField = MethodHandles.lookup().findVarHandle( + VarHandleTestMethodTypeNullRestrictedValue.class, "final_v", NullRestrictedValue.class); + + vhField = MethodHandles.lookup().findVarHandle( + VarHandleTestMethodTypeNullRestrictedValue.class, "v", NullRestrictedValue.class); + + vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestMethodTypeNullRestrictedValue.class, "static_final_v", NullRestrictedValue.class); + + vhStaticField = MethodHandles.lookup().findStaticVarHandle( + VarHandleTestMethodTypeNullRestrictedValue.class, "static_v", NullRestrictedValue.class); + + vhArray = MethodHandles.arrayElementVarHandle(NullRestrictedValue[].class); + } + + public Object[][] accessTestCaseProvider() throws Exception { + List> cases = new ArrayList<>(); + + cases.add(new VarHandleAccessTestCase("Instance field", + vhField, vh -> testInstanceFieldWrongMethodType(this, vh), + false)); + + cases.add(new VarHandleAccessTestCase("Static field", + vhStaticField, VarHandleTestMethodTypeNullRestrictedValue::testStaticFieldWrongMethodType, + false)); + + cases.add(new VarHandleAccessTestCase("Array", + vhArray, VarHandleTestMethodTypeNullRestrictedValue::testArrayWrongMethodType, + false)); + + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { + cases.add(new MethodHandleAccessTestCase("Instance field", + vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), + false)); + + cases.add(new MethodHandleAccessTestCase("Static field", + vhStaticField, f, VarHandleTestMethodTypeNullRestrictedValue::testStaticFieldWrongMethodType, + false)); + + cases.add(new MethodHandleAccessTestCase("Array", + vhArray, f, VarHandleTestMethodTypeNullRestrictedValue::testArrayWrongMethodType, + false)); + } + // Work around issue with jtreg summary reporting which truncates + // the String result of Object.toString to 30 characters, hence + // the first dummy argument + return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); + } + + @ParameterizedTest + @MethodSource("accessTestCaseProvider") + public void testAccess(String desc, AccessTestCase atc) throws Throwable { + T t = atc.get(); + int iters = atc.requiresLoop() ? ITERS : 1; + for (int c = 0; c < iters; c++) { + atc.testAccess(t); + } + } + + static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeNullRestrictedValue recv, VarHandle vh) throws Throwable { + // Get + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.get(null); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.get(Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.get(0); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.get(recv); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.get(recv); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.get(recv, Void.class); + }); + + + // Set + // Incorrect argument types + checkNPE(() -> { // null receiver + vh.set(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + vh.set(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.set(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.set(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.set(); + }); + checkWMTE(() -> { // > + vh.set(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(null); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(0); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getVolatile(recv); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getVolatile(recv); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(recv, Void.class); + }); + + + // SetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + vh.setVolatile(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + vh.setVolatile(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setVolatile(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setVolatile(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setVolatile(); + }); + checkWMTE(() -> { // > + vh.setVolatile(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetOpaque + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(null); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(0); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getOpaque(recv); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getOpaque(recv); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(recv, Void.class); + }); + + + // SetOpaque + // Incorrect argument types + checkNPE(() -> { // null receiver + vh.setOpaque(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + vh.setOpaque(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setOpaque(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setOpaque(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setOpaque(); + }); + checkWMTE(() -> { // > + vh.setOpaque(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(null); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(0); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getAcquire(recv); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAcquire(recv); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(recv, Void.class); + }); + + + // SetRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + vh.setRelease(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + vh.setRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setRelease(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setRelease(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setRelease(); + }); + checkWMTE(() -> { // > + vh.setRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndSet + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.compareAndSet(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.compareAndSet(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.compareAndSet(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.compareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.compareAndSet(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.compareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.compareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSet + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetPlain(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetPlain(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetPlain(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetPlain(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetPlain(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetPlain(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetPlain(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSet(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSet(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSet(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSet(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetAcquire(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetAcquire(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetAcquire(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetAcquire(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetRelease(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetRelease(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetRelease(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetRelease(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchange + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSet + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + // GetAndSetAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + // GetAndSetRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + } + + static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeNullRestrictedValue recv, Handles hs) throws Throwable { + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class)). + invokeExact((VarHandleTestMethodTypeNullRestrictedValue) null); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class)). + invokeExact(Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class)). + invokeExact(0); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeNullRestrictedValue.class)). + invokeExact(recv); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class)). + invokeExact(recv); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, Class.class)). + invokeExact(recv, Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + // Incorrect argument types + checkNPE(() -> { // null receiver + hs.get(am, methodType(void.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((VarHandleTestMethodTypeNullRestrictedValue) null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + hs.get(am, methodType(void.class, Class.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // value reference class + hs.get(am, methodType(void.class, VarHandleTestMethodTypeNullRestrictedValue.class, Class.class)). + invokeExact(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + hs.get(am, methodType(void.class, int.class, NullRestrictedValue.class)). + invokeExact(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + hs.get(am, methodType(void.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + hs.get(am, methodType(void.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((VarHandleTestMethodTypeNullRestrictedValue) null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // expected reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class, Class.class, NullRestrictedValue.class)). + invokeExact(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = (boolean) hs.get(am, methodType(boolean.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((VarHandleTestMethodTypeNullRestrictedValue) null, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, Class.class, NullRestrictedValue.class)). + invokeExact(recv, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class , NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeNullRestrictedValue.class , NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class , NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((VarHandleTestMethodTypeNullRestrictedValue) null, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, Class.class)). + invokeExact(recv, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class, NullRestrictedValue.class)). + invokeExact(0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, VarHandleTestMethodTypeNullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(recv, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + + } + + + static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { + // Get + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.get(); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.get(); + }); + // Incorrect arity + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.get(Void.class); + }); + + + // Set + // Incorrect argument types + checkCCE(() -> { // value reference class + vh.set(Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.set(); + }); + checkWMTE(() -> { // > + vh.set(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetVolatile + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getVolatile(); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getVolatile(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(Void.class); + }); + + + // SetVolatile + // Incorrect argument types + checkCCE(() -> { // value reference class + vh.setVolatile(Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setVolatile(); + }); + checkWMTE(() -> { // > + vh.setVolatile(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetOpaque + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getOpaque(); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getOpaque(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(Void.class); + }); + + + // SetOpaque + // Incorrect argument types + checkCCE(() -> { // value reference class + vh.setOpaque(Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setOpaque(); + }); + checkWMTE(() -> { // > + vh.setOpaque(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAcquire + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getAcquire(); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(Void.class); + }); + + + // SetRelease + // Incorrect argument types + checkCCE(() -> { // value reference class + vh.setRelease(Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setRelease(); + }); + checkWMTE(() -> { // > + vh.setRelease(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndSet + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.compareAndSet(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.compareAndSet(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.compareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.compareAndSet(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSet + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetPlain(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetPlain(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetPlain(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetPlain(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetVolatile + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSet(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSet(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSet(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetAcquire + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetAcquire(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetAcquire(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetRelease + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetRelease(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchange + // Incorrect argument types + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchange(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchange(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeAcquire + // Incorrect argument types + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeRelease + // Incorrect argument types + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSet + // Incorrect argument types + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSet(NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSet(NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSetAcquire + // Incorrect argument types + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSetRelease + // Incorrect argument types + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + } + + static void testStaticFieldWrongMethodType(Handles hs) throws Throwable { + int i = 0; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void x = (Void) hs.get(am, methodType(Void.class)). + invokeExact(); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class)). + invokeExact(); + }); + // Incorrect arity + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(Class.class)). + invokeExact(Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + hs.checkWMTEOrCCE(() -> { // value reference class + hs.get(am, methodType(void.class, Class.class)). + invokeExact(Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + hs.get(am, methodType(void.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + hs.get(am, methodType(void.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + // Incorrect argument types + hs.checkWMTEOrCCE(() -> { // expected reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = (boolean) hs.get(am, methodType(boolean.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + // Incorrect argument types + hs.checkWMTEOrCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, NullRestrictedValue.class)). + invokeExact(Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + // Incorrect argument types + hs.checkWMTEOrCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class)). + invokeExact(Void.class); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, NullRestrictedValue.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + + } + + + static void testArrayWrongMethodType(VarHandle vh) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + Arrays.fill(array, NullRestrictedValue.of((byte)20,(short)1854)); + + // Get + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.get(null, 0); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.get(Void.class, 0); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.get(0, 0); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.get(array, 0); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.get(array, 0); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.get(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.get(array, 0, Void.class); + }); + + + // Set + // Incorrect argument types + checkNPE(() -> { // null array + vh.set(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + vh.set(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.set(array, 0, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.set(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + vh.set(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.set(); + }); + checkWMTE(() -> { // > + vh.set(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetVolatile + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(null, 0); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(Void.class, 0); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(0, 0); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(array, Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getVolatile(array, 0); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getVolatile(array, 0); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getVolatile(array, 0, Void.class); + }); + + + // SetVolatile + // Incorrect argument types + checkNPE(() -> { // null array + vh.setVolatile(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + vh.setVolatile(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setVolatile(array, 0, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setVolatile(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + vh.setVolatile(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setVolatile(); + }); + checkWMTE(() -> { // > + vh.setVolatile(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetOpaque + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(null, 0); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(Void.class, 0); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(0, 0); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(array, Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getOpaque(array, 0); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getOpaque(array, 0); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getOpaque(array, 0, Void.class); + }); + + + // SetOpaque + // Incorrect argument types + checkNPE(() -> { // null array + vh.setOpaque(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + vh.setOpaque(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setOpaque(array, 0, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setOpaque(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + vh.setOpaque(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setOpaque(); + }); + checkWMTE(() -> { // > + vh.setOpaque(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAcquire + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(null, 0); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(Void.class, 0); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(0, 0); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(array, Void.class); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void x = (Void) vh.getAcquire(array, 0); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAcquire(array, 0); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAcquire(array, 0, Void.class); + }); + + + // SetRelease + // Incorrect argument types + checkNPE(() -> { // null array + vh.setRelease(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + vh.setRelease(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + vh.setRelease(array, 0, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + vh.setRelease(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + vh.setRelease(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + vh.setRelease(); + }); + checkWMTE(() -> { // > + vh.setRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndSet + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.compareAndSet(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.compareAndSet(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.compareAndSet(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.compareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.compareAndSet(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.compareAndSet(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.compareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.compareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSet + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetPlain(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetPlain(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetPlain(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetPlain(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetPlain(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetPlain(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetPlain(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSet(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSet(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSet(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSet(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSet(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSet(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetAcquire(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetAcquire(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetAcquire(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetAcquire(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // WeakCompareAndSetRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetRelease(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetRelease(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetRelease(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetRelease(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetRelease(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchange + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchange(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeAcquire + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // CompareAndExchangeRelease + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.compareAndExchangeRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSet + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(array, 0, Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSet(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSetAcquire + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(array, 0, Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetAcquire(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + // GetAndSetRelease + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(array, 0, Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + checkCCE(() -> { // reference class + Void r = (Void) vh.getAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) vh.getAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) vh.getAndSetRelease(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + + + } + + static void testArrayWrongMethodType(Handles hs) throws Throwable { + NullRestrictedValue[] array = (NullRestrictedValue[]) ValueClass.newNullRestrictedAtomicArray(NullRestrictedValue.class, 10, NullRestrictedValue.of((byte)20,(short)1854)); + Arrays.fill(array, NullRestrictedValue.of((byte)20,(short)1854)); + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class)). + invokeExact((NullRestrictedValue[]) null, 0); + }); + hs.checkWMTEOrCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, int.class)). + invokeExact(Void.class, 0); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class, int.class)). + invokeExact(0, 0); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, Class.class)). + invokeExact(array, Void.class); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void x = (Void) hs.get(am, methodType(Void.class, NullRestrictedValue[].class, int.class)). + invokeExact(array, 0); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class)). + invokeExact(array, 0); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, Class.class)). + invokeExact(array, 0, Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + // Incorrect argument types + checkNPE(() -> { // null array + hs.get(am, methodType(void.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class)). + invokeExact((NullRestrictedValue[]) null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // array reference class + hs.get(am, methodType(void.class, Class.class, int.class, NullRestrictedValue.class)). + invokeExact(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // value reference class + hs.get(am, methodType(void.class, NullRestrictedValue[].class, int.class, Class.class)). + invokeExact(array, 0, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + hs.get(am, methodType(void.class, int.class, int.class, NullRestrictedValue.class)). + invokeExact(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + hs.get(am, methodType(void.class, NullRestrictedValue[].class, Class.class, NullRestrictedValue.class)). + invokeExact(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + hs.get(am, methodType(void.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + hs.get(am, methodType(void.class, NullRestrictedValue[].class, int.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((NullRestrictedValue[]) null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // receiver reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // expected reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, Class.class, NullRestrictedValue.class)). + invokeExact(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, Class.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = (boolean) hs.get(am, methodType(boolean.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + boolean r = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + // Incorrect argument types + checkNPE(() -> { // null receiver + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact((NullRestrictedValue[]) null, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // expected reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, Class.class, NullRestrictedValue.class)). + invokeExact(array, 0, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // actual reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(0, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, Class.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, NullRestrictedValue.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + // Incorrect argument types + checkNPE(() -> { // null array + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class)). + invokeExact((NullRestrictedValue[]) null, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // array reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, Class.class, int.class, NullRestrictedValue.class)). + invokeExact(Void.class, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + hs.checkWMTEOrCCE(() -> { // value reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, Class.class)). + invokeExact(array, 0, Void.class); + }); + checkWMTE(() -> { // array primitive class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, int.class, int.class, NullRestrictedValue.class)). + invokeExact(0, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // index reference class + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, Class.class, NullRestrictedValue.class)). + invokeExact(array, Void.class, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect return type + hs.checkWMTEOrCCE(() -> { // reference class + Void r = (Void) hs.get(am, methodType(Void.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + checkWMTE(() -> { // primitive class + boolean x = (boolean) hs.get(am, methodType(boolean.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854)); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class)). + invokeExact(); + }); + checkWMTE(() -> { // > + NullRestrictedValue x = (NullRestrictedValue) hs.get(am, methodType(NullRestrictedValue.class, NullRestrictedValue[].class, int.class, NullRestrictedValue.class, Class.class)). + invokeExact(array, 0, NullRestrictedValue.of((byte)20,(short)1854), Void.class); + }); + } + + + } +} diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java index 84c68b6e71c2..c2f9afe218a1 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { static short static_v = (short)0x0123; - final short final_v = (short)0x0123; + final short final_v; - short v = (short)0x0123; + short v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeShort() { + final_v = (short)0x0123; + v = (short)0x0123; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // actual reference class short x = (short) vh.compareAndExchange(recv, (short)0x0123, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.compareAndExchange(0, (short)0x0123, (short)0x0123); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // actual reference class short x = (short) vh.compareAndExchangeAcquire(recv, (short)0x0123, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.compareAndExchangeAcquire(0, (short)0x0123, (short)0x0123); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // actual reference class short x = (short) vh.compareAndExchangeRelease(recv, (short)0x0123, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.compareAndExchangeRelease(0, (short)0x0123, (short)0x0123); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndSet(0, (short)0x0123); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndSetAcquire(0, (short)0x0123); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndSetRelease(0, (short)0x0123); }); // Incorrect return type @@ -654,7 +660,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndAdd(0, (short)0x0123); }); // Incorrect return type @@ -683,7 +689,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndAddAcquire(0, (short)0x0123); }); // Incorrect return type @@ -712,7 +718,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndAddRelease(0, (short)0x0123); }); // Incorrect return type @@ -741,7 +747,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseOr(0, (short)0x0123); }); // Incorrect return type @@ -771,7 +777,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseOrAcquire(0, (short)0x0123); }); // Incorrect return type @@ -796,27 +802,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) vh.getAndBitwiseOrRelease(null, (short)0x0123); }); checkCCE(() -> { // receiver reference class - short x = (short) vh.getAndBitwiseOr(Void.class, (short)0x0123); + short x = (short) vh.getAndBitwiseOrRelease(Void.class, (short)0x0123); }); checkWMTE(() -> { // value reference class - short x = (short) vh.getAndBitwiseOr(recv, Void.class); + short x = (short) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - short x = (short) vh.getAndBitwiseOr(0, (short)0x0123); + checkWMTE(() -> { // receiver primitive class + short x = (short) vh.getAndBitwiseOrRelease(0, (short)0x0123); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, (short)0x0123); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, (short)0x0123); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseOr(recv, (short)0x0123); + boolean x = (boolean) vh.getAndBitwiseOrRelease(recv, (short)0x0123); }); // Incorrect arity checkWMTE(() -> { // 0 - short x = (short) vh.getAndBitwiseOr(); + short x = (short) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - short x = (short) vh.getAndBitwiseOr(recv, (short)0x0123, Void.class); + short x = (short) vh.getAndBitwiseOrRelease(recv, (short)0x0123, Void.class); }); @@ -831,7 +837,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseAnd(0, (short)0x0123); }); // Incorrect return type @@ -861,7 +867,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseAndAcquire(0, (short)0x0123); }); // Incorrect return type @@ -886,27 +892,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) vh.getAndBitwiseAndRelease(null, (short)0x0123); }); checkCCE(() -> { // receiver reference class - short x = (short) vh.getAndBitwiseAnd(Void.class, (short)0x0123); + short x = (short) vh.getAndBitwiseAndRelease(Void.class, (short)0x0123); }); checkWMTE(() -> { // value reference class - short x = (short) vh.getAndBitwiseAnd(recv, Void.class); + short x = (short) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - short x = (short) vh.getAndBitwiseAnd(0, (short)0x0123); + checkWMTE(() -> { // receiver primitive class + short x = (short) vh.getAndBitwiseAndRelease(0, (short)0x0123); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, (short)0x0123); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, (short)0x0123); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseAnd(recv, (short)0x0123); + boolean x = (boolean) vh.getAndBitwiseAndRelease(recv, (short)0x0123); }); // Incorrect arity checkWMTE(() -> { // 0 - short x = (short) vh.getAndBitwiseAnd(); + short x = (short) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - short x = (short) vh.getAndBitwiseAnd(recv, (short)0x0123, Void.class); + short x = (short) vh.getAndBitwiseAndRelease(recv, (short)0x0123, Void.class); }); @@ -921,7 +927,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseXor(0, (short)0x0123); }); // Incorrect return type @@ -951,7 +957,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) vh.getAndBitwiseXorAcquire(0, (short)0x0123); }); // Incorrect return type @@ -976,27 +982,27 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) vh.getAndBitwiseXorRelease(null, (short)0x0123); }); checkCCE(() -> { // receiver reference class - short x = (short) vh.getAndBitwiseXor(Void.class, (short)0x0123); + short x = (short) vh.getAndBitwiseXorRelease(Void.class, (short)0x0123); }); checkWMTE(() -> { // value reference class - short x = (short) vh.getAndBitwiseXor(recv, Void.class); + short x = (short) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - short x = (short) vh.getAndBitwiseXor(0, (short)0x0123); + checkWMTE(() -> { // receiver primitive class + short x = (short) vh.getAndBitwiseXorRelease(0, (short)0x0123); }); // Incorrect return type checkWMTE(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, (short)0x0123); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, (short)0x0123); }); checkWMTE(() -> { // primitive class - boolean x = (boolean) vh.getAndBitwiseXor(recv, (short)0x0123); + boolean x = (boolean) vh.getAndBitwiseXorRelease(recv, (short)0x0123); }); // Incorrect arity checkWMTE(() -> { // 0 - short x = (short) vh.getAndBitwiseXor(); + short x = (short) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - short x = (short) vh.getAndBitwiseXor(recv, (short)0x0123, Void.class); + short x = (short) vh.getAndBitwiseXorRelease(recv, (short)0x0123, Void.class); }); } @@ -1114,7 +1120,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)). invokeExact(recv, (short)0x0123, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) hs.get(am, methodType(short.class, int.class , short.class, short.class)). invokeExact(0, (short)0x0123, (short)0x0123); }); @@ -1151,7 +1157,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) hs.get(am, methodType(short.class, int.class, short.class)). invokeExact(0, (short)0x0123); }); @@ -1188,7 +1194,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) hs.get(am, methodType(short.class, int.class, short.class)). invokeExact(0, (short)0x0123); }); @@ -1225,7 +1231,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class short x = (short) hs.get(am, methodType(short.class, int.class, short.class)). invokeExact(0, (short)0x0123); }); @@ -1684,7 +1690,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseOrRelease(Void.class); @@ -1747,7 +1753,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseAndRelease(Void.class); @@ -1810,7 +1816,7 @@ static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types checkWMTE(() -> { // value reference class short x = (short) vh.getAndBitwiseXorRelease(Void.class); @@ -2489,7 +2495,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class short x = (short) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class short x = (short) vh.getAndSet(0, 0, (short)0x0123); }); checkWMTE(() -> { // index reference class @@ -2522,7 +2528,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class short x = (short) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class short x = (short) vh.getAndSetAcquire(0, 0, (short)0x0123); }); checkWMTE(() -> { // index reference class @@ -2555,7 +2561,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkWMTE(() -> { // value reference class short x = (short) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class short x = (short) vh.getAndSetRelease(0, 0, (short)0x0123); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java index c5937eda15d9..30c9c76c4b43 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { static String static_v = "foo"; - final String final_v = "foo"; + final String final_v; - String v = "foo"; + String v; VarHandle vhFinalField; @@ -65,6 +65,12 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeString() { + final_v = "foo"; + v = "foo"; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -471,7 +477,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // actual reference class String x = (String) vh.compareAndExchange(recv, "foo", Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.compareAndExchange(0, "foo", "foo"); }); // Incorrect return type @@ -504,7 +510,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // actual reference class String x = (String) vh.compareAndExchangeAcquire(recv, "foo", Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.compareAndExchangeAcquire(0, "foo", "foo"); }); // Incorrect return type @@ -537,7 +543,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // actual reference class String x = (String) vh.compareAndExchangeRelease(recv, "foo", Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.compareAndExchangeRelease(0, "foo", "foo"); }); // Incorrect return type @@ -567,7 +573,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // value reference class String x = (String) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.getAndSet(0, "foo"); }); // Incorrect return type @@ -596,7 +602,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // value reference class String x = (String) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.getAndSetAcquire(0, "foo"); }); // Incorrect return type @@ -625,7 +631,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, checkCCE(() -> { // value reference class String x = (String) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) vh.getAndSetRelease(0, "foo"); }); // Incorrect return type @@ -760,7 +766,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, Class.class)). invokeExact(recv, "foo", Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) hs.get(am, methodType(String.class, int.class , String.class, String.class)). invokeExact(0, "foo", "foo"); }); @@ -797,7 +803,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class String x = (String) hs.get(am, methodType(String.class, int.class, String.class)). invokeExact(0, "foo"); }); @@ -1765,7 +1771,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class String x = (String) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class String x = (String) vh.getAndSet(0, 0, "foo"); }); checkWMTE(() -> { // index reference class @@ -1798,7 +1804,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class String x = (String) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class String x = (String) vh.getAndSetAcquire(0, 0, "foo"); }); checkWMTE(() -> { // index reference class @@ -1831,7 +1837,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class String x = (String) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class String x = (String) vh.getAndSetRelease(0, 0, "foo"); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeValue.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeValue.java index 9f7c5025cef3..217c31a8a01c 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeValue.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * @bug 8156486 * @enablePreview * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value * @run junit/othervm VarHandleTestMethodTypeValue * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true VarHandleTestMethodTypeValue * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false VarHandleTestMethodTypeValue @@ -53,9 +54,9 @@ public class VarHandleTestMethodTypeValue extends VarHandleBaseTest { static Value static_v = Value.getInstance(10); - final Value final_v = Value.getInstance(10); + final Value final_v; - Value v = Value.getInstance(10); + Value v; VarHandle vhFinalField; @@ -67,6 +68,12 @@ public class VarHandleTestMethodTypeValue extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodTypeValue() { + final_v = Value.getInstance(10); + v = Value.getInstance(10); + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -473,7 +480,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // actual reference class Value x = (Value) vh.compareAndExchange(recv, Value.getInstance(10), Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.compareAndExchange(0, Value.getInstance(10), Value.getInstance(10)); }); // Incorrect return type @@ -506,7 +513,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // actual reference class Value x = (Value) vh.compareAndExchangeAcquire(recv, Value.getInstance(10), Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.compareAndExchangeAcquire(0, Value.getInstance(10), Value.getInstance(10)); }); // Incorrect return type @@ -539,7 +546,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // actual reference class Value x = (Value) vh.compareAndExchangeRelease(recv, Value.getInstance(10), Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.compareAndExchangeRelease(0, Value.getInstance(10), Value.getInstance(10)); }); // Incorrect return type @@ -569,7 +576,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.getAndSet(0, Value.getInstance(10)); }); // Incorrect return type @@ -598,7 +605,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.getAndSetAcquire(0, Value.getInstance(10)); }); // Incorrect return type @@ -627,7 +634,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) vh.getAndSetRelease(0, Value.getInstance(10)); }); // Incorrect return type @@ -762,7 +769,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, Value x = (Value) hs.get(am, methodType(Value.class, VarHandleTestMethodTypeValue.class, Value.class, Class.class)). invokeExact(recv, Value.getInstance(10), Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) hs.get(am, methodType(Value.class, int.class , Value.class, Value.class)). invokeExact(0, Value.getInstance(10), Value.getInstance(10)); }); @@ -799,7 +806,7 @@ static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeValue recv, Value x = (Value) hs.get(am, methodType(Value.class, VarHandleTestMethodTypeValue.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class Value x = (Value) hs.get(am, methodType(Value.class, int.class, Value.class)). invokeExact(0, Value.getInstance(10)); }); @@ -1767,7 +1774,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class Value x = (Value) vh.getAndSet(0, 0, Value.getInstance(10)); }); checkWMTE(() -> { // index reference class @@ -1800,7 +1807,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class Value x = (Value) vh.getAndSetAcquire(0, 0, Value.getInstance(10)); }); checkWMTE(() -> { // index reference class @@ -1833,7 +1840,7 @@ static void testArrayWrongMethodType(VarHandle vh) throws Throwable { checkCCE(() -> { // value reference class Value x = (Value) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class Value x = (Value) vh.getAndSetRelease(0, 0, Value.getInstance(10)); }); checkWMTE(() -> { // index reference class diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index df85af59d46c..332f6ac8453d 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,11 +28,12 @@ #if[Value] * @enablePreview * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value #end[Value] * @run junit/othervm -Diters=10 -Xint VarHandleTestAccess$Type$ * - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestAccess$Type$ * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestAccess$Type$ @@ -45,6 +46,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +#if[NullRestricted] +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +#end[NullRestricted] import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -54,21 +60,21 @@ import org.junit.jupiter.params.provider.MethodSource; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { - static final $type$ static_final_v = $value1$; + static final {#if[NullRestricted]?@NullRestricted }$type$ static_final_v = $value1$; - static $type$ static_v; + static {#if[NullRestricted]?@NullRestricted }$type$ static_v = $value1$; - final $type$ final_v = $value1$; + final {#if[NullRestricted]?@NullRestricted }$type$ final_v; - $type$ v; + {#if[NullRestricted]?@NullRestricted }$type$ v; - static final $type$ static_final_v2 = $value1$; + static final {#if[NullRestricted]?@NullRestricted }$type$ static_final_v2 = $value1$; - static $type$ static_v2; + static {#if[NullRestricted]?@NullRestricted }$type$ static_v2 = $value1$; - final $type$ final_v2 = $value1$; + final {#if[NullRestricted]?@NullRestricted }$type$ final_v2; - $type$ v2; + {#if[NullRestricted]?@NullRestricted }$type$ v2; VarHandle vhFinalField; @@ -82,7 +88,15 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { #if[Object] VarHandle vhArrayObject; + #end[Object] + public VarHandleTestAccess$Type$() { + final_v = $value1$; + v = $value1$; + final_v2 = $value1$; + v2 = $value1$; + super(); + } VarHandle[] allocate(boolean same) { List vhs = new ArrayList<>(); @@ -308,12 +322,22 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { cases.add(new VarHandleAccessTestCase("Instance field unsupported", vhField, vh -> testInstanceFieldUnsupported(this, vh), false)); +#if[NullRestricted] + cases.add(new VarHandleAccessTestCase("Instance field null pointer exception", + vhField, vh -> testInstanceFieldNullPointerException(this, vh), + false)); +#end[NullRestricted] cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestAccess$Type$::testStaticField)); cases.add(new VarHandleAccessTestCase("Static field unsupported", vhStaticField, VarHandleTestAccess$Type$::testStaticFieldUnsupported, false)); +#if[NullRestricted] + cases.add(new VarHandleAccessTestCase("Static field null pointer exception", + vhStaticField, VarHandleTestAccess$Type$::testStaticFieldNullPointerException, + false)); +#end[NullRestricted] cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestAccess$Type$::testArray)); @@ -332,6 +356,11 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { vhArrayObject, VarHandleTestAccess$Type$::testArrayStoreException, false)); #end[Object] +#if[NullRestricted] + cases.add(new VarHandleAccessTestCase("Array null pointer exception", + vhArrayObject, VarHandleTestAccess$Type$::testArrayNullPointerException, + false)); +#end[NullRestricted] // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -365,7 +394,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { // Lazy { $type$ x = ($type$) vh.getAcquire(recv); - assertEquals($value1$, x, "getRelease $type$ value"); + assertEquals($value1$, x, "getAcquire $type$ value"); } // Opaque @@ -509,7 +538,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { // Lazy { $type$ x = ($type$) vh.getAcquire(); - assertEquals($value1$, x, "getRelease $type$ value"); + assertEquals($value1$, x, "getAcquire $type$ value"); } // Opaque @@ -851,7 +880,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { vh.set(recv, $value1$); $type$ o = ($type$) vh.getAndAddRelease(recv, $value2$); - assertEquals($value1$, o, "getAndAddRelease$type$"); + assertEquals($value1$, o, "getAndAddRelease $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(($type$)($value1$ + $value2$), x, "getAndAddRelease $type$ value"); } @@ -1260,7 +1289,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { vh.set($value1$); $type$ o = ($type$) vh.getAndAddRelease($value2$); - assertEquals($value1$, o, "getAndAddRelease$type$"); + assertEquals($value1$, o, "getAndAddRelease $type$"); $type$ x = ($type$) vh.get(); assertEquals(($type$)($value1$ + $value2$), x, "getAndAddRelease $type$ value"); } @@ -1455,7 +1484,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { static void testArray(VarHandle vh) { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; for (int i = 0; i < array.length; i++) { // Plain @@ -1672,7 +1701,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { vh.set(array, i, $value1$); $type$ o = ($type$) vh.getAndAddRelease(array, i, $value2$); - assertEquals($value1$, o, "getAndAddRelease$type$"); + assertEquals($value1$, o, "getAndAddRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(($type$)($value1$ + $value2$), x, "getAndAddRelease $type$ value"); } @@ -1767,7 +1796,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } static void testArrayUnsupported(VarHandle vh) { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; int i = 0; #if[!CAS] @@ -1870,7 +1899,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) { final int ci = i; @@ -2006,10 +2035,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { #end[Bitwise] } } - #if[Object] + static void testArrayStoreException(VarHandle vh) throws Throwable { - Object[] array = new $type$[10]; + Object[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; Arrays.fill(array, $value1$); Object value = new Object(); @@ -2034,60 +2063,300 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { }); // CompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.compareAndSet(array, 0, $value1$, value); }); // WeakCompareAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, value); }); // WeakCompareAndSetVolatile - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSet(array, 0, $value1$, value); }); // WeakCompareAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, value); }); // WeakCompareAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, value); }); // CompareAndExchange - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, value); }); // CompareAndExchangeAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, value); }); // CompareAndExchangeRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, value); }); // GetAndSet - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.getAndSet(array, 0, value); }); // GetAndSetAcquire - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.getAndSetAcquire(array, 0, value); }); // GetAndSetRelease - checkASE(() -> { // receiver reference class + checkASE(() -> { $type$ x = ($type$) vh.getAndSetRelease(array, 0, value); }); } #end[Object] +#if[NullRestricted] + + static void testInstanceFieldNullPointerException(VarHandleTestAccess$Type$ recv, VarHandle vh) throws Throwable { + $type$ value = null; + + // Set + checkNPE(() -> { + vh.set(recv, value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(recv, value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(recv, value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(recv, value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet(recv, $value1$, value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain(recv, $value1$, value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet(recv, $value1$, value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease(recv, $value1$, value); + }); + + // CompareAndExchange + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchange(recv, $value1$, value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, value); + }); + + // GetAndSet + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSet(recv, value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetAcquire(recv, value); + }); + + // GetAndSetRelease + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetRelease(recv, value); + }); + } + + static void testStaticFieldNullPointerException(VarHandle vh) throws Throwable { + $type$ value = null; + + // Set + checkNPE(() -> { + vh.set(value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet($value1$, value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain($value1$, value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet($value1$, value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire($value1$, value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease($value1$, value); + }); + + // CompareAndExchange + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchange($value1$, value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeAcquire($value1$, value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeRelease($value1$, value); + }); + + // GetAndSet + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSet(value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetAcquire(value); + }); + + // GetAndSetRelease + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetRelease(value); + }); + } + + static void testArrayNullPointerException(VarHandle vh) throws Throwable { + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; + $type$ value = null; + + // Set + checkNPE(() -> { + vh.set(array, 0, value); + }); + + // SetVolatile + checkNPE(() -> { + vh.setVolatile(array, 0, value); + }); + + // SetOpaque + checkNPE(() -> { + vh.setOpaque(array, 0, value); + }); + + // SetRelease + checkNPE(() -> { + vh.setRelease(array, 0, value); + }); + + // CompareAndSet + checkNPE(() -> { + boolean r = vh.compareAndSet(array, 0, $value1$, value); + }); + + // WeakCompareAndSet + checkNPE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, value); + }); + + // WeakCompareAndSetVolatile + checkNPE(() -> { + boolean r = vh.weakCompareAndSet(array, 0, $value1$, value); + }); + + // WeakCompareAndSetAcquire + checkNPE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, value); + }); + + // WeakCompareAndSetRelease + checkNPE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, value); + }); + + // CompareAndExchange + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, value); + }); + + // CompareAndExchangeAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, value); + }); + + // CompareAndExchangeRelease + checkNPE(() -> { + $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, value); + }); + + // GetAndSet + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSet(array, 0, value); + }); + + // GetAndSetAcquire + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetAcquire(array, 0, value); + }); + + // GetAndSetRelease + checkNPE(() -> { + $type$ x = ($type$) vh.getAndSetRelease(array, 0, value); + }); + } +#end[NullRestricted] } diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 9a40bfb27806..f30a43390251 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,8 @@ /* * @test * @bug 8154556 - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$ * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAs$Type$ * @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAs$Type$ @@ -59,9 +59,9 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { public List setupVarHandleSources(boolean same) { // Combinations of VarHandle byte[] or ByteBuffer List vhss = new ArrayList<>(); - for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + for (MemoryMode endianness : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { - ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ByteOrder bo = endianness == MemoryMode.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; Class arrayType; @@ -77,12 +77,12 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { } VarHandleSource aeh = new VarHandleSource( MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, - endianess, MemoryMode.READ_WRITE); + endianness, MemoryMode.READ_WRITE); vhss.add(bbh); } return vhss; @@ -1627,7 +1627,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { // Lazy { $type$ x = ($type$) vh.getAcquire(array, i); - assertEquals(v, x, "getRelease $type$ value"); + assertEquals(v, x, "getAcquire $type$ value"); } // Opaque diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template index 076befb5685b..9d5dd44516b0 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,10 @@ #if[Value] * @enablePreview * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value #end[Value] - * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations - * to hit compilation thresholds + * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop set to 2000 iterations + * hits compilation thresholds * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccess$Type$ */ @@ -40,6 +41,11 @@ import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; +#if[NullRestricted] +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +#end[NullRestricted] import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; @@ -48,13 +54,13 @@ import org.junit.jupiter.params.provider.MethodSource; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { - static final $type$ static_final_v = $value1$; + static final {#if[NullRestricted]?@NullRestricted }$type$ static_final_v = $value1$; - static $type$ static_v; + static {#if[NullRestricted]?@NullRestricted }$type$ static_v = $value1$; - final $type$ final_v = $value1$; + final {#if[NullRestricted]?@NullRestricted }$type$ final_v; - $type$ v; + {#if[NullRestricted]?@NullRestricted }$type$ v; VarHandle vhFinalField; @@ -66,6 +72,12 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodHandleAccess$Type$() { + final_v = $value1$; + v = $value1$; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -92,12 +104,22 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { cases.add(new MethodHandleAccessTestCase("Instance field unsupported", vhField, f, hs -> testInstanceFieldUnsupported(this, hs), false)); +#if[NullRestricted] + cases.add(new MethodHandleAccessTestCase("Instance field null pointer exception", + vhField, f, hs -> testInstanceFieldNullPointerException(this, hs), + false)); +#end[NullRestricted] cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticField)); cases.add(new MethodHandleAccessTestCase("Static field unsupported", vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticFieldUnsupported, false)); +#if[NullRestricted] + cases.add(new MethodHandleAccessTestCase("Static field null pointer exception", + vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticFieldNullPointerException, + false)); +#end[NullRestricted] cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArray)); @@ -107,6 +129,11 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { cases.add(new MethodHandleAccessTestCase("Array index out of bounds", vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayIndexOutOfBounds, false)); +#if[NullRestricted] + cases.add(new MethodHandleAccessTestCase("Array null pointer exception", + vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayNullPointerException, + false)); +#end[NullRestricted] } // Work around issue with jtreg summary reporting which truncates @@ -293,11 +320,31 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { // Compare set and get { + hs.get(TestAccessMode.SET).invokeExact(recv, $value1$); + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value2$); assertEquals($value1$, o, "getAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals($value2$, x, "getAndSet $type$ value"); } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, $value1$); + + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(recv, $value2$); + assertEquals($value1$, o, "getAndSetAcquire $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals($value2$, x, "getAndSetAcquire $type$ value"); + } + + { + hs.get(TestAccessMode.SET).invokeExact(recv, $value1$); + + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(recv, $value2$); + assertEquals($value1$, o, "getAndSetRelease $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals($value2$, x, "getAndSetRelease $type$ value"); + } #end[CAS] #if[AtomicAdd] @@ -620,7 +667,7 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value2$, $value3$); assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals($value1$, x, "failing weakCompareAndSetRe $type$ value"); + assertEquals($value1$, x, "failing weakCompareAndSet $type$ value"); } // Compare set and get @@ -633,7 +680,6 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { assertEquals($value2$, x, "getAndSet $type$ value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact($value1$); @@ -643,7 +689,6 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { assertEquals($value2$, x, "getAndSetAcquire $type$ value"); } - // Compare set and get { hs.get(TestAccessMode.SET).invokeExact($value1$); @@ -811,7 +856,7 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { static void testArray(Handles hs) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; for (int i = 0; i < array.length; i++) { // Plain @@ -954,10 +999,10 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value1$, $value3$); - assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals($value2$, x, "failing weakCompareAndSetAcquire $type$ value"); + assertEquals($value2$, x, "failing weakCompareAndSetRelease $type$ value"); } { @@ -1127,7 +1172,7 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } static void testArrayUnsupported(Handles hs) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; final int i = 0; #if[!CAS] @@ -1168,7 +1213,7 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } static void testArrayIndexOutOfBounds(Handles hs) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) { final int ci = i; @@ -1222,5 +1267,99 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { #end[Bitwise] } } +#if[NullRestricted] + + static void testInstanceFieldNullPointerException(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable { + $type$ value = null; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(recv, value); + }); + } +#if[CAS] + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(recv, $value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact(recv, value); + }); + } +#end[CAS] + } + + static void testStaticFieldNullPointerException(Handles hs) throws Throwable { + $type$ value = null; + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(value); + }); + } +#if[CAS] + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact($value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact($value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact(value); + }); + } +#end[CAS] + } + + static void testArrayNullPointerException(Handles hs) throws Throwable { + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; + $type$ value = null; + + final int i = 0; + for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { + checkNPE(am, () -> { + hs.get(am).invokeExact(array, i, value); + }); + } +#if[CAS] + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { + checkNPE(am, () -> { + boolean r = (boolean) hs.get(am).invokeExact(array, i, $value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$, value); + }); + } + + for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { + checkNPE(am, () -> { + $type$ r = ($type$) hs.get(am).invokeExact(array, i, value); + }); + } +#end[CAS] + } +#end[NullRestricted] } diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template index e1717283115f..726b8ccb5c2e 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #if[Value] * @enablePreview * @modules java.base/jdk.internal.vm.annotation + * java.base/jdk.internal.value #end[Value] * @run junit/othervm VarHandleTestMethodType$Type$ * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true VarHandleTestMethodType$Type$ @@ -44,6 +45,11 @@ import java.util.List; import static java.lang.invoke.MethodType.*; +#if[NullRestricted] +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; + +#end[NullRestricted] import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.params.ParameterizedTest; @@ -51,13 +57,13 @@ import org.junit.jupiter.params.provider.MethodSource; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { - static final $type$ static_final_v = $value1$; + static final {#if[NullRestricted]?@NullRestricted }$type$ static_final_v = $value1$; - static $type$ static_v = $value1$; + static {#if[NullRestricted]?@NullRestricted }$type$ static_v = $value1$; - final $type$ final_v = $value1$; + final {#if[NullRestricted]?@NullRestricted }$type$ final_v; - $type$ v = $value1$; + {#if[NullRestricted]?@NullRestricted }$type$ v; VarHandle vhFinalField; @@ -69,6 +75,12 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { VarHandle vhArray; + public VarHandleTestMethodType$Type$() { + final_v = $value1$; + v = $value1$; + super(); + } + @BeforeAll public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -476,7 +488,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // actual reference class $type$ x = ($type$) vh.compareAndExchange(recv, $value1$, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.compareAndExchange(0, $value1$, $value1$); }); // Incorrect return type @@ -509,7 +521,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // actual reference class $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.compareAndExchangeAcquire(0, $value1$, $value1$); }); // Incorrect return type @@ -542,7 +554,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // actual reference class $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.compareAndExchangeRelease(0, $value1$, $value1$); }); // Incorrect return type @@ -572,7 +584,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSet(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndSet(0, $value1$); }); // Incorrect return type @@ -601,7 +613,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSetAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndSetAcquire(0, $value1$); }); // Incorrect return type @@ -630,7 +642,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSetRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndSetRelease(0, $value1$); }); // Incorrect return type @@ -661,7 +673,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndAdd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndAdd(0, $value1$); }); // Incorrect return type @@ -690,7 +702,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndAddAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndAddAcquire(0, $value1$); }); // Incorrect return type @@ -719,7 +731,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndAddRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndAddRelease(0, $value1$); }); // Incorrect return type @@ -750,7 +762,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseOr(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseOr(0, $value1$); }); // Incorrect return type @@ -780,7 +792,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseOrAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseOrAcquire(0, $value1$); }); // Incorrect return type @@ -805,27 +817,27 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) vh.getAndBitwiseOrRelease(null, $value1$); }); checkCCE(() -> { // receiver reference class - $type$ x = ($type$) vh.getAndBitwiseOr(Void.class, $value1$); + $type$ x = ($type$) vh.getAndBitwiseOrRelease(Void.class, $value1$); }); check{#if[Object]?CCE:WMTE}(() -> { // value reference class - $type$ x = ($type$) vh.getAndBitwiseOr(recv, Void.class); + $type$ x = ($type$) vh.getAndBitwiseOrRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - $type$ x = ($type$) vh.getAndBitwiseOr(0, $value1$); + checkWMTE(() -> { // receiver primitive class + $type$ x = ($type$) vh.getAndBitwiseOrRelease(0, $value1$); }); // Incorrect return type check{#if[Object]?CCE:WMTE}(() -> { // reference class - Void r = (Void) vh.getAndBitwiseOr(recv, $value1$); + Void r = (Void) vh.getAndBitwiseOrRelease(recv, $value1$); }); checkWMTE(() -> { // primitive class - $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOr(recv, $value1$); + $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrRelease(recv, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 - $type$ x = ($type$) vh.getAndBitwiseOr(); + $type$ x = ($type$) vh.getAndBitwiseOrRelease(); }); checkWMTE(() -> { // > - $type$ x = ($type$) vh.getAndBitwiseOr(recv, $value1$, Void.class); + $type$ x = ($type$) vh.getAndBitwiseOrRelease(recv, $value1$, Void.class); }); @@ -840,7 +852,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseAnd(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseAnd(0, $value1$); }); // Incorrect return type @@ -870,7 +882,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseAndAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseAndAcquire(0, $value1$); }); // Incorrect return type @@ -895,27 +907,27 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) vh.getAndBitwiseAndRelease(null, $value1$); }); checkCCE(() -> { // receiver reference class - $type$ x = ($type$) vh.getAndBitwiseAnd(Void.class, $value1$); + $type$ x = ($type$) vh.getAndBitwiseAndRelease(Void.class, $value1$); }); check{#if[Object]?CCE:WMTE}(() -> { // value reference class - $type$ x = ($type$) vh.getAndBitwiseAnd(recv, Void.class); + $type$ x = ($type$) vh.getAndBitwiseAndRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - $type$ x = ($type$) vh.getAndBitwiseAnd(0, $value1$); + checkWMTE(() -> { // receiver primitive class + $type$ x = ($type$) vh.getAndBitwiseAndRelease(0, $value1$); }); // Incorrect return type check{#if[Object]?CCE:WMTE}(() -> { // reference class - Void r = (Void) vh.getAndBitwiseAnd(recv, $value1$); + Void r = (Void) vh.getAndBitwiseAndRelease(recv, $value1$); }); checkWMTE(() -> { // primitive class - $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAnd(recv, $value1$); + $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndRelease(recv, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 - $type$ x = ($type$) vh.getAndBitwiseAnd(); + $type$ x = ($type$) vh.getAndBitwiseAndRelease(); }); checkWMTE(() -> { // > - $type$ x = ($type$) vh.getAndBitwiseAnd(recv, $value1$, Void.class); + $type$ x = ($type$) vh.getAndBitwiseAndRelease(recv, $value1$, Void.class); }); @@ -930,7 +942,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseXor(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseXor(0, $value1$); }); // Incorrect return type @@ -960,7 +972,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseXorAcquire(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) vh.getAndBitwiseXorAcquire(0, $value1$); }); // Incorrect return type @@ -985,27 +997,27 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) vh.getAndBitwiseXorRelease(null, $value1$); }); checkCCE(() -> { // receiver reference class - $type$ x = ($type$) vh.getAndBitwiseXor(Void.class, $value1$); + $type$ x = ($type$) vh.getAndBitwiseXorRelease(Void.class, $value1$); }); check{#if[Object]?CCE:WMTE}(() -> { // value reference class - $type$ x = ($type$) vh.getAndBitwiseXor(recv, Void.class); + $type$ x = ($type$) vh.getAndBitwiseXorRelease(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class - $type$ x = ($type$) vh.getAndBitwiseXor(0, $value1$); + checkWMTE(() -> { // receiver primitive class + $type$ x = ($type$) vh.getAndBitwiseXorRelease(0, $value1$); }); // Incorrect return type check{#if[Object]?CCE:WMTE}(() -> { // reference class - Void r = (Void) vh.getAndBitwiseXor(recv, $value1$); + Void r = (Void) vh.getAndBitwiseXorRelease(recv, $value1$); }); checkWMTE(() -> { // primitive class - $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXor(recv, $value1$); + $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorRelease(recv, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 - $type$ x = ($type$) vh.getAndBitwiseXor(); + $type$ x = ($type$) vh.getAndBitwiseXorRelease(); }); checkWMTE(() -> { // > - $type$ x = ($type$) vh.getAndBitwiseXor(recv, $value1$, Void.class); + $type$ x = ($type$) vh.getAndBitwiseXorRelease(recv, $value1$, Void.class); }); #end[Bitwise] } @@ -1125,7 +1137,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)). invokeExact(recv, $value1$, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class , $type$.class, $type$.class)). invokeExact(0, $value1$, $value1$); }); @@ -1162,7 +1174,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)). invokeExact(0, $value1$); }); @@ -1201,7 +1213,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)). invokeExact(0, $value1$); }); @@ -1240,7 +1252,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). invokeExact(recv, Void.class); }); - checkWMTE(() -> { // reciever primitive class + checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)). invokeExact(0, $value1$); }); @@ -1705,7 +1717,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); - // GetAndBitwiseOrReleaseRelease + // GetAndBitwiseOrRelease // Incorrect argument types check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseOrRelease(Void.class); @@ -1768,7 +1780,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); - // GetAndBitwiseAndReleaseRelease + // GetAndBitwiseAndRelease // Incorrect argument types check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseAndRelease(Void.class); @@ -1831,7 +1843,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); - // GetAndBitwiseXorReleaseRelease + // GetAndBitwiseXorRelease // Incorrect argument types check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndBitwiseXorRelease(Void.class); @@ -2026,7 +2038,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { static void testArrayWrongMethodType(VarHandle vh) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; Arrays.fill(array, $value1$); // Get @@ -2518,7 +2530,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSet(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class $type$ x = ($type$) vh.getAndSet(0, 0, $value1$); }); checkWMTE(() -> { // index reference class @@ -2551,7 +2563,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSetAcquire(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class $type$ x = ($type$) vh.getAndSetAcquire(0, 0, $value1$); }); checkWMTE(() -> { // index reference class @@ -2584,7 +2596,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { check{#if[Object]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) vh.getAndSetRelease(array, 0, Void.class); }); - checkWMTE(() -> { // reciarrayever primitive class + checkWMTE(() -> { // array primitive class $type$ x = ($type$) vh.getAndSetRelease(0, 0, $value1$); }); checkWMTE(() -> { // index reference class @@ -3006,7 +3018,7 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { } static void testArrayWrongMethodType(Handles hs) throws Throwable { - $type$[] array = new $type$[10]; + $type$[] array = {#if[NullRestricted]?($type$[]) ValueClass.newNullRestrictedAtomicArray($type$.class, 10, $value1$):new $type$[10]}; Arrays.fill(array, $value1$); for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { diff --git a/test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh b/test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh index 1d860551aa8b..bbed2bcaf83c 100644 --- a/test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh +++ b/test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh @@ -9,7 +9,7 @@ SPP=build.tools.spp.Spp # desirable to generate code using ASM which will allow more flexibility # in the kinds of tests that are generated. -for type in boolean byte short char int long float double String Value +for type in boolean byte short char int long float double String Value NullRestrictedValue do Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" args="-K$type -Dtype=$type -DType=$Type" @@ -37,6 +37,9 @@ do Value) args="$args -KObject -KValue" ;; + NullRestrictedValue) + args="$args -KObject -KValue -KNullRestricted" + ;; esac wrong_primitive_type=boolean @@ -93,6 +96,10 @@ do value2="Value.getInstance(20)" value3="Value.getInstance(30)" ;; + NullRestrictedValue) + value1="NullRestrictedValue.of((byte)20,(short)1854)" + value2="NullRestrictedValue.of((byte)-42,(short)1854)" + value3="NullRestrictedValue.of((byte)20,(short)-31083)" esac args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3 -Dwrong_primitive_type=$wrong_primitive_type" diff --git a/test/jdk/java/lang/runtime/CarriersTest.java b/test/jdk/java/lang/runtime/CarriersTest.java deleted file mode 100644 index 9b805f2c832c..000000000000 --- a/test/jdk/java/lang/runtime/CarriersTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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. - */ - -/* - * @test - * @summary Test features provided by the Carriers class. - * @modules java.base/java.lang.runtime - * @enablePreview true - * @compile --patch-module java.base=${test.src} CarriersTest.java - * @run main/othervm --patch-module java.base=${test.class.path} java.lang.runtime.CarriersTest - */ - -package java.lang.runtime; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import java.util.Arrays; -import java.util.List; - -public class CarriersTest { - public static void main(String[] args) throws Throwable { - primitivesTest(); - primitivesTestLarge(); - limitsTest(); - } - - static void assertTrue(boolean test, String message) { - if (!test) { - throw new RuntimeException(message); - } - } - - static final int MAX_COMPONENTS = 254; - - static void primitivesTest() throws Throwable { - MethodType methodType = - MethodType.methodType(Object.class, byte.class, short.class, - char.class, int.class, long.class, - float.class, double.class, - boolean.class, String.class); - MethodHandle constructor = Carriers.initializingConstructor(methodType); - Object object = (Object)constructor.invokeExact((byte)0xFF, (short)0xFFFF, - 'C', 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFL, - 1.0f / 3.0f, 1.0 / 3.0, - true, "abcde"); - List components = Carriers.components(methodType); - assertTrue((byte)components.get(0).invokeExact(object) == (byte)0xFF, - "primitive byte test failure"); - assertTrue((short)components.get(1).invokeExact(object) == (short)0xFFFF, - "primitive short test failure"); - assertTrue((char)components.get(2).invokeExact(object) == 'C', - "primitive char test failure"); - assertTrue((int)components.get(3).invokeExact(object) == 0xFFFFFFFF, - "primitive int test failure"); - assertTrue((long)components.get(4).invokeExact(object) == 0xFFFFFFFFFFFFFFFFL, - "primitive long test failure"); - assertTrue((float)components.get(5).invokeExact(object) == 1.0f / 3.0f, - "primitive float test failure"); - assertTrue((double)components.get(6).invokeExact(object) == 1.0 / 3.0, - "primitive double test failure"); - assertTrue((boolean)components.get(7).invokeExact(object), - "primitive boolean test failure"); - assertTrue("abcde".equals((String)components.get(8).invokeExact(object)), - "primitive String test failure"); - } - - static void primitivesTestLarge() throws Throwable { - MethodType methodType = - MethodType.methodType(Object.class, byte.class, short.class, - char.class, int.class, long.class, - float.class, double.class, - boolean.class, String.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class, - Object.class, Object.class,Object.class,Object.class - ); - MethodHandle constructor = Carriers.initializingConstructor(methodType); - Object object = (Object)constructor.invokeExact((byte)0xFF, (short)0xFFFF, - 'C', 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFL, - 1.0f / 3.0f, 1.0 / 3.0, - true, "abcde", - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null, - (Object)null, (Object)null, (Object)null, (Object)null - ); - List components = Carriers.components(methodType); - assertTrue((byte)components.get(0).invokeExact(object) == (byte)0xFF, - "large primitive byte test failure"); - assertTrue((short)components.get(1).invokeExact(object) == (short)0xFFFF, - "large primitive short test failure"); - assertTrue((char)components.get(2).invokeExact(object) == 'C', - "large primitive char test failure"); - assertTrue((int)components.get(3).invokeExact(object) == 0xFFFFFFFF, - "large primitive int test failure"); - assertTrue((long)components.get(4).invokeExact(object) == 0xFFFFFFFFFFFFFFFFL, - "large primitive long test failure"); - assertTrue((float)components.get(5).invokeExact(object) == 1.0f / 3.0f, - "large primitive float test failure"); - assertTrue((double)components.get(6).invokeExact(object) == 1.0 / 3.0, - "large primitive double test failure"); - assertTrue((boolean)components.get(7).invokeExact(object), - "large primitive boolean test failure"); - assertTrue("abcde".equals((String)components.get(8).invokeExact(object)), - "large primitive String test failure"); - } - - static void limitsTest() { - boolean passed; - - passed = false; - try { - Class[] ptypes = new Class[MAX_COMPONENTS + 1]; - Arrays.fill(ptypes, Object.class); - MethodType methodType = MethodType.methodType(Object.class, ptypes); - MethodHandle constructor = Carriers.constructor(methodType); - } catch (IllegalArgumentException ex) { - passed = true; - } - - if (!passed) { - throw new RuntimeException("failed to report too many components "); - } - - passed = false; - try { - Class[] ptypes = new Class[MAX_COMPONENTS / 2 + 1]; - Arrays.fill(ptypes, long.class); - MethodType methodType = MethodType.methodType(Object.class, ptypes); - MethodHandle constructor = Carriers.constructor(methodType); - } catch (IllegalArgumentException ex) { - passed = true; - } - - if (!passed) { - throw new RuntimeException("failed to report too many components "); - } - } -} diff --git a/test/jdk/java/net/httpclient/IdleConnectionTimeoutReuseTest.java b/test/jdk/java/net/httpclient/IdleConnectionTimeoutReuseTest.java new file mode 100644 index 000000000000..a99115717c00 --- /dev/null +++ b/test/jdk/java/net/httpclient/IdleConnectionTimeoutReuseTest.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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.net.http.HttpClient; +import java.net.http.HttpClient.Version; +import java.net.http.HttpRequest; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +import jdk.httpclient.test.lib.common.HttpServerAdapters; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.test.lib.Utils; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; + +import org.junit.jupiter.api.function.ThrowingSupplier; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import javax.net.ssl.SSLContext; + +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static java.net.http.HttpClient.Version.HTTP_1_1; +import static java.net.http.HttpClient.Version.HTTP_2; +import static java.net.http.HttpClient.Version.HTTP_3; +import static java.net.http.HttpOption.H3_DISCOVERY; +import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; +import static java.net.http.HttpResponse.BodyHandlers.discarding; +import static jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange.RSPBODY_EMPTY; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +/* + * @test + * @summary Verify that a connection with overdue idle timeout is not reused + * + * @library /test/lib + * /test/jdk/java/net/httpclient/lib + * + * @comment Why do we force the usage of virtual threads at the selector? The + * problem we are stressing is not an issue specific to virtual threads + * or their usage in the HTTP client. We're forcing the usage of + * virtual threads, because this way it is easier to starve the thread + * pool used by the selector. This issue could very well be observed + * using platform threads, but it would be more difficult to reproduce + * reliably. + * + * @comment Why do we skip the test on Windows? On Windows, the selector + * implementation (i.e., `WEPollSelectorImpl`) blocks a virtual thread + * without releasing its carrier. With both + * `jdk.virtualThreadScheduler.{parallelism,maxPoolSize}` set to 1, no + * carrier remains to compensate for the blocked selector, and the + * initial client request cannot make progress. We could increase the + * VT scheduler capacity, but this contradicts with the reason we fix + * it to 1 in the first place: to starve the HTTP Client selector + * threads. + * + * @comment Why do we configure both `{quic,tcp}.selector.useVirtualThreads`? + * As of date, connection eviction is triggered by the selector of + * `HttpClientImpl`, not by the QUIC selector. Being prudent, we fix + * both to virtual threads. + * + * @comment Why are both `parallelism` and `maxPoolSize` 1? Because the default + * carrier thread pool (i.e., FJP) requires `parallelism <= maxPoolSize` + * and having 1 thread in the pool is easier to make it starve. + * + * @requires os.family != "windows" + * + * @run junit/othervm + * -Djdk.httpclient.keepalive.timeout=1 + * -Djdk.internal.httpclient.quic.selector.useVirtualThreads=always + * -Djdk.internal.httpclient.tcp.selector.useVirtualThreads=always + * -Djdk.virtualThreadScheduler.parallelism=1 + * -Djdk.virtualThreadScheduler.maxPoolSize=1 + * ${test.main.class} + */ + +class IdleConnectionTimeoutReuseTest { + + /** + * @implNote + * This test has several timing-sensitive assumptions. If these assumptions + * hold, the test will verify the subject behavior. If not, the test will + * and should pass anyway. Therefore, it is not a problem if the assumptions + * don't hold. Local testing has shown that these assumptions do hold almost + * always. + */ + @ParameterizedTest + @EnumSource(InfraFactory.class) + void testDelayedIdleTimeout(InfraFactory infraFactory) throws Throwable { + try (var server = infraFactory.createStartedServer(); + var client = infraFactory.createClient()) { + + // Issue the 1st request establishing the connection + var request = infraFactory.createRequest(server); + var response1 = client.send(request, discarding()); + assertEquals(200, response1.statusCode()); + var response1Label = response1.connectionLabel().orElseThrow(); + + // Give the worker that closes the first exchange time to register the + // idle timer. Note that this is timing-sensitive, and hence, an + // assumption. + Thread.sleep(Utils.adjustTimeout(200)); + + // In the JTreg `@test` configuration above, + // + // 1. Virtual thread pool is configured to have at most 1 carrier thread. + // 2. HTTP client's selector is configured to use virtual threads. + // + // Occupy that single carrier thread to block the HTTP client's selector + // from processing idle timeouts. + var carrierBlockerStarted = new CountDownLatch(1); + var carrierBlockerStopped = new AtomicBoolean(); + var carrierBlocker = Thread.ofVirtual().start(() -> { + carrierBlockerStarted.countDown(); + while (!carrierBlockerStopped.get()) { + Thread.onSpinWait(); + } + }); + carrierBlockerStarted.await(); + + try { + + // The virtual selector cannot process the 1s timeout while its + // only carrier is occupied. Let the timeout become overdue + // before reserving the connection for the 2nd request. + Thread.sleep(Utils.adjustTimeout(1500)); + + // Execute the 2nd request + var response2Future = client.sendAsync(request, discarding()); + + // Release the carrier thread blocker, so both idle timeout + // processing and serving of the 2nd request can proceed. We + // first sleep some to allow the latter to proceed as much as + // possible. This increases its chances to get executed first. + Thread.sleep(Utils.adjustTimeout(100)); + carrierBlockerStopped.set(true); + carrierBlocker.join(); + + // At this stage, we cannot know for certain if idle timeout + // processing or serving of the 2nd request gets executed first. + // If it is the latter, we will be verifying what this test aims + // to stress. In either case, the 2nd request should not be + // served using the timed out connection. + var response2 = response2Future.join(); + assertEquals(200, response2.statusCode()); + assertNotEquals( + response1Label, response2.connectionLabel().orElseThrow(), + "The 1st overdue connection should not have been reused!"); + + } finally { + carrierBlockerStopped.set(true); + carrierBlocker.join(); + } + + } + } + + enum InfraFactory { + + H1C(false, HTTP_1_1), + + H1S(true, HTTP_1_1), + + H2C(false, HTTP_2), + + H2S(true, HTTP_2), + + H3( + true, + HTTP_3, + () -> HttpTestServer.create(HTTP_3_URI_ONLY, SSL_CONTEXT), + requestBuilder -> requestBuilder + .version(HTTP_3) + .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY)); + + private final boolean secure; + + private final Version version; + + private final ThrowingSupplier serverFactory; + + private final Consumer requestBuilderConfigurer; + + private final String handlerPath = "/idle-timeout-" + this; + + InfraFactory(boolean secure, Version version) { + this( + secure, + version, + () -> HttpTestServer.create(version, secure ? SSL_CONTEXT : null), + requestBuilder -> requestBuilder.version(version)); + } + + InfraFactory( + boolean secure, + Version version, + ThrowingSupplier serverFactory, + Consumer requestBuilderConfigurer) { + this.secure = secure; + this.version = version; + this.serverFactory = serverFactory; + this.requestBuilderConfigurer = requestBuilderConfigurer; + } + + private HttpTestServer createStartedServer() throws Throwable { + var server = serverFactory.get(); + server.addHandler(this::send200, handlerPath); + server.start(); + return server; + } + + private void send200(HttpTestExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, RSPBODY_EMPTY); + } + + private HttpRequest createRequest(HttpTestServer server) { + var requestUri = URIBuilder.newBuilder() + .scheme(secure ? "https" : "http") + .host(server.getAddress().getAddress()) + .port(server.getAddress().getPort()) + .path(handlerPath) + .buildUnchecked(); + var requestBuilder = HttpRequest.newBuilder(requestUri); + requestBuilderConfigurer.accept(requestBuilder); + return requestBuilder.build(); + } + + private HttpClient createClient() { + var clientBuilder = HttpServerAdapters.createClientBuilderFor(version) + .proxy(NO_PROXY); + if (secure) { + clientBuilder.sslContext(SSL_CONTEXT); + } + return clientBuilder.build(); + } + + } + + private static final SSLContext SSL_CONTEXT = SimpleSSLContext.findSSLContext(); + +} diff --git a/test/jdk/java/nio/file/Files/TemporaryFiles.java b/test/jdk/java/nio/file/Files/TemporaryFiles.java index 4e971bc54276..fe37c32b4ee1 100644 --- a/test/jdk/java/nio/file/Files/TemporaryFiles.java +++ b/test/jdk/java/nio/file/Files/TemporaryFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,95 +22,150 @@ */ /* @test - * @bug 4313887 6838333 7006126 7023034 + * @bug 4313887 6838333 7006126 7023034 8391574 * @summary Unit test for Files.createTempXXX - * @library .. + * @run junit ${test.main.class} */ -import java.nio.file.*; -import static java.nio.file.StandardOpenOption.*; -import java.nio.file.attribute.*; import java.io.IOException; + +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import static java.nio.file.StandardOpenOption.*; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; import java.util.Set; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +class TemporaryFiles { + + // system-wide tmp dir + static final Path SYS_TMPDIR = Path.of(System.getProperty("java.io.tmpdir")); + + // local test tmp dir + static Path TEST_TMPDIR; + + @BeforeAll + static void setup() throws Exception { + TEST_TMPDIR = Files.createTempDirectory(Path.of("."), "adir"); + } -public class TemporaryFiles { + @AfterAll + static void cleanup() throws Exception { + Files.delete(TEST_TMPDIR); + } - static void checkInDirectory(Path file, Path dir) { - if (dir == null) - dir = Paths.get(System.getProperty("java.io.tmpdir")); - if (!file.getParent().equals(dir)) - throw new RuntimeException("Not in expected directory"); + /** + * Returns directory, prefix, and suffix combinations for temporary file tests. + */ + static Stream tempFiles() { + return Stream.of( + Arguments.arguments(null, null, null), + Arguments.arguments(null, "blah", null), + Arguments.arguments(null, "", null), + Arguments.arguments(null, null, ".dat"), + Arguments.arguments(null, null, ""), + Arguments.arguments(null, "blah", ".dat"), + Arguments.arguments(TEST_TMPDIR, null, null), + Arguments.arguments(TEST_TMPDIR, "blah", null), + Arguments.arguments(TEST_TMPDIR, "", null), + Arguments.arguments(TEST_TMPDIR, null, ".dat"), + Arguments.arguments(TEST_TMPDIR, null, ""), + Arguments.arguments(TEST_TMPDIR, "blah", ".dat") + ); } - static void testTempFile(String prefix, String suffix, Path dir) - throws IOException - { + @ParameterizedTest + @MethodSource("tempFiles") + void testTempFile(Path dir, String prefix, String suffix) throws Exception { Path file = (dir == null) ? Files.createTempFile(prefix, suffix) : Files.createTempFile(dir, prefix, suffix); try { // check file name String name = file.getFileName().toString(); - if (prefix != null && !name.startsWith(prefix)) - throw new RuntimeException("Should start with " + prefix); - if (suffix == null && !name.endsWith(".tmp")) - throw new RuntimeException("Should end with .tmp"); - if (suffix != null && !name.endsWith(suffix)) - throw new RuntimeException("Should end with " + suffix); + if (prefix != null && !prefix.isEmpty()) { + assertTrue(name.startsWith(prefix), "Should start with " + prefix); + } + if (suffix == null || !suffix.isEmpty()) { + String expectedSuffix = (suffix != null) ? suffix : ".tmp"; + assertTrue(name.endsWith(expectedSuffix), "Should end with " + expectedSuffix); + } // check file is in expected directory - checkInDirectory(file, dir); + Path expectedDir = (dir != null) ? dir : SYS_TMPDIR; + assertEquals(expectedDir, file.getParent(), "Not in expected directory"); - // check that file can be opened for reading and writing + // check file can be opened for reading and writing Files.newByteChannel(file, READ).close(); Files.newByteChannel(file, WRITE).close(); - Files.newByteChannel(file, READ,WRITE).close(); + Files.newByteChannel(file, READ, WRITE).close(); // check file permissions are 0600 or more secure if (Files.getFileStore(file).supportsFileAttributeView("posix")) { Set perms = Files.getPosixFilePermissions(file); perms.remove(PosixFilePermission.OWNER_READ); perms.remove(PosixFilePermission.OWNER_WRITE); - if (!perms.isEmpty()) - throw new RuntimeException("Temporary file is not secure"); + assertTrue(perms.isEmpty(), "Temporary file is not secure"); } } finally { Files.delete(file); } } - static void testTempFile(String prefix, String suffix) - throws IOException - { - testTempFile(prefix, suffix, null); + /** + * Returns directory and prefix combinations for temporary directory tests. + */ + static Stream tempDirectories() { + return Stream.of( + Arguments.arguments(null, null), + Arguments.arguments(null, "blah"), + Arguments.arguments(null, ""), + Arguments.arguments(TEST_TMPDIR, null), + Arguments.arguments(TEST_TMPDIR, "blah"), + Arguments.arguments(TEST_TMPDIR, "") + ); } - static void testTempDirectory(String prefix, Path dir) throws IOException { + @ParameterizedTest + @MethodSource("tempDirectories") + void testTempDirectory(Path dir, String prefix) throws Exception { Path subdir = (dir == null) ? Files.createTempDirectory(prefix) : Files.createTempDirectory(dir, prefix); try { - // check file name - String name = subdir.getFileName().toString(); - if (prefix != null && !name.startsWith(prefix)) - throw new RuntimeException("Should start with " + prefix); + // check directory name + if (prefix != null && !prefix.isEmpty()) { + String name = subdir.getFileName().toString(); + assertTrue(name.startsWith(prefix), "Should start with " + prefix); + } // check directory is in expected directory - checkInDirectory(subdir, dir); + Path expectedDir = (dir != null) ? dir : SYS_TMPDIR; + assertEquals(expectedDir, subdir.getParent(), "Not in expected directory"); - // check directory is empty - DirectoryStream stream = Files.newDirectoryStream(subdir); - try { - if (stream.iterator().hasNext()) - throw new RuntimeException("Tempory directory not empty"); - } finally { - stream.close(); + // check directory is readable (and empty) + try (DirectoryStream stream = Files.newDirectoryStream(subdir)) { + assertFalse(stream.iterator().hasNext(), "Temporary directory not empty"); } - // check that we can create file in directory + // check directory is writable Path file = Files.createFile(subdir.resolve("foo")); try { - Files.newByteChannel(file, READ,WRITE).close(); + Files.newByteChannel(file, READ, WRITE).close(); } finally { Files.delete(file); } @@ -121,77 +176,215 @@ static void testTempDirectory(String prefix, Path dir) throws IOException { perms.remove(PosixFilePermission.OWNER_READ); perms.remove(PosixFilePermission.OWNER_WRITE); perms.remove(PosixFilePermission.OWNER_EXECUTE); - if (!perms.isEmpty()) - throw new RuntimeException("Temporary directory is not secure"); + assertTrue(perms.isEmpty(), "Temporary directory is not secure"); } } finally { Files.delete(subdir); } } - static void testTempDirectory(String prefix) throws IOException { - testTempDirectory(prefix, null); + /** + * Returns file permissions to restrict perissions of temporay file/directory. + */ + static Stream permissions() { + return Stream.of( + "---------", + "r--------", + "-w-------", + "--x------", + "rwx------", + "---r-----", + "----w----", + "-----x---", + "---rwx---", + "------r--", + "-------w-", + "--------x", + "------rwx", + "r--r-----", + "r--r--r--", + "rw-rw----", + "rwxrwx---", + "rw-rw-r--", + "r-xr-x---", + "r-xr-xr-x", + "rwxrwxrwx" + ); } - static void testInvalidFileTemp(String prefix, String suffix) throws IOException { - try { - Path file = Files.createTempFile(prefix, suffix); - Files.delete(file); - throw new RuntimeException("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { } + /** + * Checks that the actual permissions are not less secure than the requested. + */ + void checkSecure(Set requested, Set actual) { + assertTrue(actual.stream().allMatch(requested::contains), () -> + "Actual permissions: " + PosixFilePermissions.toString(actual) + + ", requested: " + PosixFilePermissions.toString(requested) + + " - file is less secure than requested"); } - public static void main(String[] args) throws IOException { - // temporary-file directory - testTempFile("blah", ".dat"); - testTempFile("blah", null); - testTempFile(null, ".dat"); - testTempFile(null, null); - testTempDirectory("blah"); - testTempDirectory(null); + @ParameterizedTest + @MethodSource("permissions") + @DisabledOnOs(OS.WINDOWS) + void testPosixAttributes(String permsAsString) throws Exception { + Set perms = PosixFilePermissions.fromString(permsAsString); + FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); - // a given directory - Path dir = Files.createTempDirectory("tmpdir"); - try { - testTempFile("blah", ".dat", dir); - testTempFile("blah", null, dir); - testTempFile(null, ".dat", dir); - testTempFile(null, null, dir); - testTempDirectory("blah", dir); - testTempDirectory(null, dir); - } finally { - Files.delete(dir); + if (Files.getFileStore(SYS_TMPDIR).supportsFileAttributeView("posix")) { + Path file = Files.createTempFile("blah", ".tmp", attr); + try { + checkSecure(perms, Files.getPosixFilePermissions(file)); + } finally { + Files.delete(file); + } + Path dir = Files.createTempDirectory("blah", attr); + try { + checkSecure(perms, Files.getPosixFilePermissions(dir)); + } finally { + Files.delete(dir); + } + } + + if (Files.getFileStore(TEST_TMPDIR).supportsFileAttributeView("posix")) { + Path file = Files.createTempFile(TEST_TMPDIR, "blah", ".tmp", attr); + try { + checkSecure(perms, Files.getPosixFilePermissions(file)); + } finally { + Files.delete(file); + } + Path dir = Files.createTempDirectory(TEST_TMPDIR, "blah", attr); + try { + checkSecure(perms, Files.getPosixFilePermissions(dir)); + } finally { + Files.delete(dir); + } } + } - // invalid prefix and suffix - testInvalidFileTemp("../blah", null); - testInvalidFileTemp("dir/blah", null); - testInvalidFileTemp("blah", ".dat/foo"); + /** + * Test Files.createTempXXX with an attribute that cannot be set. + */ + @Test + void testUnknownAttribute() { + var attr = new FileAttribute() { + @Override public String name() { return "unknown"; } + @Override public String value() { return "foo"; } + }; + assertThrows(UnsupportedOperationException.class, () -> Files.createTempFile("blah", ".dat", attr)); + assertThrows(UnsupportedOperationException.class, () -> Files.createTempDirectory("blah", attr)); + } - // nulls - try { - Files.createTempFile("blah", ".tmp", (FileAttribute[])null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - try { - Files.createTempFile("blah", ".tmp", new FileAttribute[] { null }); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - try { - Files.createTempDirectory("blah", (FileAttribute[])null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - try { - Files.createTempDirectory("blah", new FileAttribute[] { null }); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - try { - Files.createTempFile((Path)null, "blah", ".tmp"); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - try { - Files.createTempDirectory((Path)null, "blah"); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } + /** + * Test Files.createTempXXX with a directory that does not exist. + */ + @Test + void testDirDoesNotExist() { + Path dir = Path.of("DoesNotExist"); + assertTrue(Files.notExists(dir)); + assertThrows(IOException.class, () -> Files.createTempFile(dir, null, null)); + assertThrows(IOException.class, () -> Files.createTempFile(dir, "blah", null)); + assertThrows(IOException.class, () -> Files.createTempFile(dir, null, ".dat")); + assertThrows(IOException.class, () -> Files.createTempFile(dir, "blah", ".dat")); + assertThrows(IOException.class, () -> Files.createTempDirectory(dir, null)); + assertThrows(IOException.class, () -> Files.createTempDirectory(dir, "blah")); + } + + /** + * Returns prefixes that should be rejected. + */ + static Stream badPrefixes() { + return Stream.of( + "/blah", + "../blah", + "dir/blah", + "foo\0bar" + ); + } + + @ParameterizedTest + @MethodSource("badPrefixes") + void testBadPrefix(String prefix) { + Path dir = Path.of("."); + assertThrows(IllegalArgumentException.class, () -> Files.createTempFile(prefix, null)); + assertThrows(IllegalArgumentException.class, () -> Files.createTempFile(dir, prefix, null)); + assertThrows(IllegalArgumentException.class, () -> Files.createTempDirectory(prefix)); + assertThrows(IllegalArgumentException.class, () -> Files.createTempDirectory(dir, prefix)); + } + + /** + * Returns prefixes that should be rejected on Windows. + */ + static Stream badWindowsPrefixes() { + return Stream.of( + "\\\\server", + "\\\\server\\share", + "\\\\?\\UNC\\server\\share", + "C:\\temp\\blah", + "C:temp\\blah", + "C:blah" + ); + } + + /** + * Tests prefixes that should be rejected on Windows. + */ + @ParameterizedTest + @MethodSource("badWindowsPrefixes") + @EnabledOnOs(OS.WINDOWS) + void testBadWindowsPrefixes(String prefix) { + testBadPrefix(prefix); + } + + /** + * Returns suffixes that should be rejected. + */ + static Stream badSuffixes() { + return Stream.of( + ".dat/foo", + "foo\0bar" + ); + } + + @ParameterizedTest + @MethodSource("badSuffixes") + void testBadSuffix(String suffix) { + Path dir = Path.of("."); + assertThrows(IllegalArgumentException.class, () -> Files.createTempFile("blah", suffix)); + assertThrows(IllegalArgumentException.class, () -> Files.createTempFile(dir, "blah", suffix)); + } + + /** + * Returns suffixes that should be rejected on Windows. + */ + static Stream badWindowsSuffixes() { + return Stream.of( + ".dat\\foo", + ":" + ); + } + + @ParameterizedTest + @MethodSource("badWindowsSuffixes") + @EnabledOnOs(OS.WINDOWS) + void testBadWindowsSuffix(String suffix) { + testBadSuffix(suffix); + } + + /** + * Test nulls. + */ + @Test + void testNulls() { + assertThrows(NullPointerException.class, + () -> Files.createTempFile("blah", ".tmp", (FileAttribute[]) null)); + assertThrows(NullPointerException.class, + () -> Files.createTempFile("blah", ".tmp", new FileAttribute[] { null })); + assertThrows(NullPointerException.class, + () -> Files.createTempDirectory("blah", (FileAttribute[]) null)); + assertThrows(NullPointerException.class, + () -> Files.createTempDirectory("blah", new FileAttribute[] { null })); + assertThrows(NullPointerException.class, + () -> Files.createTempFile((Path)null, "blah", ".tmp")); + assertThrows(NullPointerException.class, + () -> Files.createTempDirectory((Path)null, "blah")); } } diff --git a/test/jdk/java/security/KeyStore/PKCS12/WriteP12Test.java b/test/jdk/java/security/KeyStore/PKCS12/WriteP12Test.java index 535cb8c8f4c5..56fdf4190c3f 100644 --- a/test/jdk/java/security/KeyStore/PKCS12/WriteP12Test.java +++ b/test/jdk/java/security/KeyStore/PKCS12/WriteP12Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,6 @@ * @summary Write different types p12 key store to Check the write related * APIs. * @run main WriteP12Test - * @enablePreview */ public class WriteP12Test { diff --git a/test/jdk/java/security/KeyStore/TestKeyStoreBasic.java b/test/jdk/java/security/KeyStore/TestKeyStoreBasic.java index e39793cf1b79..eda7d0f29d83 100644 --- a/test/jdk/java/security/KeyStore/TestKeyStoreBasic.java +++ b/test/jdk/java/security/KeyStore/TestKeyStoreBasic.java @@ -36,7 +36,6 @@ /* * @test * @bug 8048621 8133090 8167371 8236671 8374808 - * @enablePreview * @summary Test basic operations with keystores (jks, jceks, pkcs12) * @author Yu-Ching Valerie PENG */ diff --git a/test/jdk/java/security/PEM/PEMDecoderTest.java b/test/jdk/java/security/PEM/PEMDecoderTest.java index dc0fe18956d2..96fc2705c90f 100644 --- a/test/jdk/java/security/PEM/PEMDecoderTest.java +++ b/test/jdk/java/security/PEM/PEMDecoderTest.java @@ -30,7 +30,6 @@ * @modules java.base/sun.security.pkcs * java.base/sun.security.util * @summary Testing basic PEM API decoding - * @enablePreview */ import javax.crypto.EncryptedPrivateKeyInfo; diff --git a/test/jdk/java/security/PEM/PEMEncoderTest.java b/test/jdk/java/security/PEM/PEMEncoderTest.java index 4d205f2f9bf3..1b6abf8c011d 100644 --- a/test/jdk/java/security/PEM/PEMEncoderTest.java +++ b/test/jdk/java/security/PEM/PEMEncoderTest.java @@ -28,7 +28,6 @@ * @bug 8298420 * @library /test/lib * @summary Testing basic PEM API encoding - * @enablePreview * @modules java.base/sun.security.util * @run main PEMEncoderTest PBEWithHmacSHA256AndAES_128 * @run main/othervm -Djava.security.properties=${test.src}/java.security-anotherAlgo diff --git a/test/jdk/java/security/PEM/PEMMultiThreadTest.java b/test/jdk/java/security/PEM/PEMMultiThreadTest.java index f345a3c129dc..a22eae364637 100644 --- a/test/jdk/java/security/PEM/PEMMultiThreadTest.java +++ b/test/jdk/java/security/PEM/PEMMultiThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @bug 8298420 * @library /test/lib * @summary Testing PEM API is thread safe - * @enablePreview * @modules java.base/sun.security.util */ diff --git a/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java b/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java index e38d18dc9439..c1bfae338b3f 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java +++ b/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4519462 * @summary Verify Sun CertPathBuilder implementation handles certificates with no extensions - * @enablePreview */ import java.security.PEMDecoder; diff --git a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java index 1f48b077aca5..7a5c1f47855a 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java +++ b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java @@ -36,7 +36,6 @@ * @run main/othervm DisableRevocation subca * @run main/othervm DisableRevocation subci * @run main/othervm DisableRevocation alice - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java index fc49aa69f842..e3fa6ec796c2 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java +++ b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java @@ -32,7 +32,6 @@ * @bug 6852744 8133489 * @summary PIT b61: PKI test suite fails because self signed certificates * are being rejected - * @enablePreview * @modules java.base/sun.security.util * @run main/othervm -Djava.security.debug=certpath KeyUsageMatters subca * @run main/othervm -Djava.security.debug=certpath KeyUsageMatters subci diff --git a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java index 95b02811a202..bb7344fd9593 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java +++ b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java @@ -33,7 +33,6 @@ * @summary PIT b61: PKI test suite fails because self signed certificates * are being rejected * @modules java.base/sun.security.util - * @enablePreview * @run main/othervm StatusLoopDependency subca * @run main/othervm StatusLoopDependency subci * @run main/othervm StatusLoopDependency alice diff --git a/test/jdk/java/security/cert/CertPathValidator/OCSP/FailoverToCRL.java b/test/jdk/java/security/cert/CertPathValidator/OCSP/FailoverToCRL.java index 3bf801b8255c..25e4b7aa5650 100644 --- a/test/jdk/java/security/cert/CertPathValidator/OCSP/FailoverToCRL.java +++ b/test/jdk/java/security/cert/CertPathValidator/OCSP/FailoverToCRL.java @@ -32,7 +32,6 @@ * @bug 6383095 * @summary CRL revoked certificate failures masked by OCSP failures * @run main/othervm FailoverToCRL - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevel.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevel.java index 81b6a4d1351b..30918c176bb8 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevel.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevel.java @@ -33,7 +33,6 @@ * @bug 6720721 * @summary CRL check with circular depency support needed * @run main/othervm CircularCRLOneLevel - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevelRevoked.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevelRevoked.java index caedb27f823b..786ee2f17bfb 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevelRevoked.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLOneLevelRevoked.java @@ -33,7 +33,6 @@ * @bug 6720721 * @summary CRL check with circular depency support needed * @run main/othervm CircularCRLOneLevelRevoked - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java index 4a5d9fe409a1..1acf92dd770e 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java @@ -32,7 +32,6 @@ * * @bug 6720721 * @summary CRL check with circular depency support needed - * @enablePreview * @run main/othervm CircularCRLTwoLevel * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java index 909b3e53a148..cad7b421d4b5 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java @@ -31,8 +31,7 @@ * @test * * @bug 6720721 - * @summary CRL check with circular depency support needed - * @enablePreview + * @summary CRL check with circular dependency support needed * @run main/othervm CircularCRLTwoLevelRevoked * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithRID.java b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithRID.java index d7dcfc6b6d53..a35223c43185 100644 --- a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithRID.java +++ b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithRID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * * @bug 6845286 * @summary Add regression test for name constraints - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithUnexpectedRID.java b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithUnexpectedRID.java index 333e9b19f300..00014f9be8ae 100644 --- a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithUnexpectedRID.java +++ b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithUnexpectedRID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * * @bug 6845286 * @summary Add regression test for name constraints - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithoutRID.java b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithoutRID.java index 63b4f921e0e0..82323d937762 100644 --- a/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithoutRID.java +++ b/test/jdk/java/security/cert/CertPathValidator/nameConstraints/NameConstraintsWithoutRID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * * @bug 6845286 * @summary Add regression test for name constraints - * @enablePreview * @author Xuelei Fan */ diff --git a/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java b/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java index 58d3c37975a7..309bdb4e9963 100644 --- a/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java +++ b/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8132926 * @summary PKIXParameters built with public key form of TrustAnchor causes * NPE during cert path building/validation - * @enablePreview * @run main ValWithAnchorByName */ diff --git a/test/jdk/java/util/concurrent/forkjoin/GetMultipleWaiters.java b/test/jdk/java/util/concurrent/forkjoin/GetMultipleWaiters.java new file mode 100644 index 000000000000..d595747b65d4 --- /dev/null +++ b/test/jdk/java/util/concurrent/forkjoin/GetMultipleWaiters.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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 8390870 + * @summary ForkJoinTask.get must honor its timeout and interrupts even + * when another thread is waiting on the same task. + * @run junit/othervm/timeout=20 GetMultipleWaiters + */ + +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +class GetMultipleWaiters { + + /** + * get() must be interruptible while another thread is waiting on the + * same task. + */ + @Test + void testGet() throws Exception { + var task = ForkJoinTask.adapt(() -> {}); + var thrown = new Throwable[1]; + + var a = startThreadAndAwaitState(() -> { + try { + task.get(); + } catch (Throwable t) { + thrown[0] = t; + } + }, "Get-waiter-A", Thread.State.WAITING); + var b = startThreadAndAwaitState(() -> { + try { + task.get(); + } catch (Throwable ignore) { + } + }, "Get-waiter-B", Thread.State.WAITING); + + try { + a.interrupt(); + a.join(); + + assertInstanceOf(InterruptedException.class, thrown[0]); + } finally { + task.complete(null); + b.join(); + } + } + + /** + * get(long, TimeUnit) must time out while another thread is waiting + * on the same task. + */ + @Test + void testTimedGet() throws Exception { + var task = ForkJoinTask.adapt(() -> {}); + var thrown = new Throwable[1]; + + var a = startThreadAndAwaitState(() -> { + try { + task.get(1, TimeUnit.SECONDS); + } catch (Throwable t) { + thrown[0] = t; + } + }, "TimedGet-waiter-A", Thread.State.TIMED_WAITING); + var b = startThreadAndAwaitState(() -> { + try { + task.get(); + } catch (Throwable ignore) { + } + }, "TimedGet-waiter-B", Thread.State.WAITING); + + try { + a.join(); + + assertInstanceOf(TimeoutException.class, thrown[0]); + } finally { + task.complete(null); + b.join(); + } + } + + static Thread startThreadAndAwaitState(Runnable r, String name, Thread.State state) throws Exception { + var t = new Thread(r, name); + t.start(); + while (t.getState() != state) + Thread.sleep(1); + return t; + } +} diff --git a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/Encrypt.java b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/Encrypt.java index 631410efb210..dbc70c12b6ef 100644 --- a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/Encrypt.java +++ b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/Encrypt.java @@ -29,7 +29,6 @@ * @modules java.base/sun.security.util * @bug 8298420 * @summary Testing encryptKey - * @enablePreview */ import sun.security.util.Pem; diff --git a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java index a4bfd4e47d60..0de72330860e 100644 --- a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java +++ b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java @@ -27,7 +27,6 @@ * @test * @bug 8298420 * @summary Testing getKey - * @enablePreview */ import javax.crypto.EncryptedPrivateKeyInfo; diff --git a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeyPair.java b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeyPair.java index fd4df8366abb..4eaaf645c4f2 100644 --- a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeyPair.java +++ b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeyPair.java @@ -28,7 +28,6 @@ * @bug 8360563 * @library /test/lib * @summary Testing getKeyPair using ML-KEM - * @enablePreview * @modules java.base/sun.security.util */ diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java index fd1569b4eeaf..a1d1eae4d237 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ * @test * @bug 7068321 * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server - * @enablePreview * @run main/othervm SSLSocketSNISensitive PKIX www.example.com * @run main/othervm SSLSocketSNISensitive SunX509 www.example.com * @run main/othervm SSLSocketSNISensitive PKIX www.example.net diff --git a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java index fc6369a2bbc7..5bb8548ec617 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java +++ b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ /* * @test * @bug 8205111 - * @enablePreview * @summary Test TLS with different types of supported keys. * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256 * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 diff --git a/test/jdk/javax/swing/text/JTextComponent/TextComponentDragEnabledTest.java b/test/jdk/javax/swing/text/JTextComponent/TextComponentDragEnabledTest.java new file mode 100644 index 000000000000..a5f031a14e2b --- /dev/null +++ b/test/jdk/javax/swing/text/JTextComponent/TextComponentDragEnabledTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=headful + * @bug 8388884 + * @key headful + * @summary Checks dragEnabled defaults and explicit settings across installed L&Fs + * @run main TextComponentDragEnabledTest + */ + +/* + * @test id=headless + * @bug 8388884 + * @summary Checks dragEnabled defaults and explicit settings across installed L&Fs + * @run main/othervm -Djava.awt.headless=true TextComponentDragEnabledTest + */ + +import java.util.List; +import java.util.function.Supplier; + +import java.awt.GraphicsEnvironment; + +import javax.swing.JEditorPane; +import javax.swing.JFormattedTextField; +import javax.swing.JPasswordField; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.text.JTextComponent; +import javax.swing.UnsupportedLookAndFeelException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class TextComponentDragEnabledTest { + + private static final String AQUA_LAF = "com.apple.laf.AquaLookAndFeel"; + + private static final List> TEXT_COMPONENTS = List.of( + JTextField::new, + JTextArea::new, + JTextPane::new, + JEditorPane::new, + JPasswordField::new, + JFormattedTextField::new + ); + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + try { + runTest(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + private static void runTest() throws Exception { + testDefaultsForAllLookAndFeels(); + if (!GraphicsEnvironment.isHeadless()) { + testExplicitSettingsForAllLookAndFeels(); + } + } + + private static void testDefaultsForAllLookAndFeels() + throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing L&F " + laf.getClassName()); + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException e) { + System.out.println("Skipping unsupported L&F: " + laf.getClassName()); + continue; + } + + for (Supplier supplier : TEXT_COMPONENTS) { + JTextComponent component = supplier.get(); + boolean expected = AQUA_LAF.equals(laf.getClassName()) + && !GraphicsEnvironment.isHeadless(); + checkDragEnabled(component, expected, + "new component under " + laf.getClassName()); + } + } + } + + private static void testExplicitSettingsForAllLookAndFeels() + throws Exception { + for (boolean expected : new boolean[] { false, true }) { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + + for (Supplier supplier : TEXT_COMPONENTS) { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + JTextComponent component = supplier.get(); + component.setDragEnabled(expected); + + UIManager.setLookAndFeel(laf.getClassName()); + component.updateUI(); + + checkDragEnabled(component, expected, + "after switching to " + laf.getClassName()); + + testSerialization(component, expected); + } + } + } + } + + private static void testSerialization(JTextComponent component, boolean expected) throws Exception { + JTextComponent copy = serializeAndDeserialize(component); + checkDragEnabled(copy, expected, "after deserializing application value"); + } + + private static JTextComponent serializeAndDeserialize(JTextComponent component) + throws Exception { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + try (ObjectOutputStream out = new ObjectOutputStream(bytes)) { + out.writeObject(component); + } + + try (ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bytes.toByteArray()))) { + return (JTextComponent) in.readObject(); + } + } + + private static void checkDragEnabled(JTextComponent component, + boolean expected, + String msg) { + boolean actual = component.getDragEnabled(); + if (actual != expected) { + throw new RuntimeException(component.getClass().getName() + + ": " + msg + + "; expected dragEnabled=" + expected + + ", actual=" + actual); + } + } +} diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java index 1f0d95394722..e514161a3dca 100644 --- a/test/jdk/jdk/classfile/VerifierSelfTest.java +++ b/test/jdk/jdk/classfile/VerifierSelfTest.java @@ -32,8 +32,7 @@ import java.lang.classfile.constantpool.PoolEntry; import java.lang.constant.ClassDesc; -import static java.lang.classfile.ClassFile.ACC_STATIC; -import static java.lang.classfile.ClassFile.JAVA_8_VERSION; +import static java.lang.classfile.ClassFile.*; import static java.lang.constant.ConstantDescs.*; import java.lang.constant.MethodTypeDesc; @@ -61,6 +60,7 @@ import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -508,4 +508,122 @@ void testInvokeSpecialInterfacePatch() { assertTrue(errors.getFirst().getMessage().contains("interface method to invoke is not in a direct superinterface"), errors.getFirst().getMessage()); } } + + @Test // JDK-8357037 + void testCodeEndsWithSwitch() { + var testClass = ClassDesc.of("Test"); + var context = ClassFile.of(); + var bytes = context.build(testClass, clb -> clb + .withVersion(JAVA_28_VERSION, 0) + .withMethodBody("tableSwitchFoo", MTD_void, 0, cob -> { + Label skip = cob.newLabel(); + cob.goto_(skip); + Label back = cob.newBoundLabel(); + cob.return_() + .labelBinding(skip) + .iconst_0() + .tableswitch(0, 2, back, List.of()); + }) + .withMethodBody("lookupSwitchFoo", MTD_void, 0, cob -> { + Label skip = cob.newLabel(); + cob.goto_(skip); + Label back = cob.newBoundLabel(); + cob.return_() + .labelBinding(skip) + .iconst_0() + .lookupswitch(back, List.of()); + })); + assertEquals(List.of(), context.verify(bytes)); + } + + @Test // JDK-8388631 + void testControlFlowAlias() { + var testName = "Test"; + var testDesc = ClassDesc.of(testName); + var bytes = ClassFile.of(StackMapsOption.DROP_STACK_MAPS).build(testDesc, clb -> clb + .withVersion(latestMajorVersion(), PREVIEW_MINOR_VERSION) + .withFlags(ACC_PUBLIC | ACC_IDENTITY) + .withField("f", CD_int, ACC_STRICT_INIT) + .withMethodBody(INIT_NAME, MethodTypeDesc.of(CD_void, CD_boolean), 0, cob -> { + Label ifEnd = cob.newLabel(); + cob.iload(1) + .ifeq(ifEnd) + .aload(0) + .iconst_1() + .putfield(testDesc, "f", CD_int) + .labelBinding(ifEnd) + .aload(0) + .invokespecial(CD_Object, INIT_NAME, MTD_void) + .return_() + .with(StackMapTableAttribute.of(List.of(StackMapFrameInfo.of(ifEnd, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS, StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(), + List.of(cob.constantPool().nameAndTypeEntry("f", CD_int)))))); + })); + ClassModel cm = ClassFile.of().parse(bytes); + var stackMapsTable = cm.methods().getFirst().findAttribute(Attributes.code()).orElseThrow() + .findAttribute(Attributes.stackMapTable()).orElseThrow(); + assertNotEquals(246, stackMapsTable.entries().getFirst().frameType()); + assertNotEquals(List.of(), ClassFile.of().verify(cm)); // field f not initialized + } + + @Test // JDK-8389840 + @Disabled // Need StackMapFrameInfo.of fix + void testUninitializedThisOnStackOnly() { + var testName = "Test"; + var testDesc = ClassDesc.of(testName); + var bytes = ClassFile.of(StackMapsOption.DROP_STACK_MAPS).build(testDesc, clb -> clb + .withVersion(latestMajorVersion(), PREVIEW_MINOR_VERSION) + .withFlags(ACC_PUBLIC | ACC_IDENTITY) + .withField("f", CD_int, ACC_STRICT_INIT) + .withMethodBody(INIT_NAME, MTD_void, 0, cob -> { + List frames = new ArrayList<>(); + cob.aload(0) // stack for invokespecial + .dup() // stack for putfield + .iconst_4() + .iconst_m1() // stack for astore + .istore(0) // nuke uninitializedThis from locals + .iconst_3(); // stack for branch + var elseLabel = cob.newLabel(); + var endIfLabel = cob.newLabel(); + cob.ifeq(elseLabel) + .putfield(testDesc, "f", CD_int) + .goto_(endIfLabel) + .labelBinding(elseLabel); + frames.add(StackMapFrameInfo.of(elseLabel, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS, + StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS, + StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(cob.constantPool().nameAndTypeEntry("f", CD_int)))); + cob.putfield(testDesc, "f", CD_int) + .labelBinding(endIfLabel); + frames.add(StackMapFrameInfo.of(endIfLabel, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS), + List.of())); + cob.invokespecial(CD_Object, INIT_NAME, MTD_void); + var else2Label = cob.newLabel(); + var endIf2Label = cob.newLabel(); + cob.iconst_1() + .ifeq(else2Label) + .nop() + .goto_(endIf2Label) + .labelBinding(else2Label); + frames.add(StackMapFrameInfo.of(else2Label, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(), + List.of())); + cob.nop() + .labelBinding(endIf2Label); + frames.add(StackMapFrameInfo.of(endIf2Label, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER), + List.of(), + List.of())); + cob.return_() + .with(StackMapTableAttribute.of(frames)); + })); + + assertEquals(List.of(), ClassFile.of().verify(bytes)); + } } diff --git a/test/jdk/jdk/incubator/vector/VectorLanewiseOpCompatibleWithTest.java b/test/jdk/jdk/incubator/vector/VectorLanewiseOpCompatibleWithTest.java new file mode 100644 index 000000000000..5c12554c643e --- /dev/null +++ b/test/jdk/jdk/incubator/vector/VectorLanewiseOpCompatibleWithTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @bug 8389844 + * @modules jdk.incubator.vector + * @run testng VectorLanewiseOpCompatibleWithTest + */ + +public class VectorLanewiseOpCompatibleWithTest { + private static final List> ELEMENT_TYPES = List.of( + byte.class, + short.class, + int.class, + long.class, + Float16.class, + float.class, + double.class); + + private static final List OPERATORS = vectorOperators(); + + private static List vectorOperators() { + List operators = new ArrayList<>(); + for (var field : VectorOperators.class.getFields()) { + if (Modifier.isStatic(field.getModifiers()) && + VectorOperators.Operator.class.isAssignableFrom(field.getType())) { + try { + operators.add((VectorOperators.Operator) field.get(null)); + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } + } + operators.sort(Comparator.comparing(VectorOperators.Operator::name)); + return List.copyOf(operators); + } + + @DataProvider + public Object[][] unsupportedOperatorProvider() { + return operatorProvider(false); + } + + @DataProvider + public Object[][] supportedOperatorProvider() { + return operatorProvider(true); + } + + private static Object[][] operatorProvider(boolean compatible) { + return ELEMENT_TYPES.stream() + .flatMap(elementType -> Arrays.stream(VectorShape.values()) + .map(shape -> VectorSpecies.of(elementType, shape))) + .flatMap(species -> OPERATORS.stream() + .filter(op -> op instanceof VectorOperators.Unary || + op instanceof VectorOperators.Binary || + op instanceof VectorOperators.Ternary) + // These operators are more restrictive, exclude for now. + .filter(op -> op != VectorOperators.COMPRESS_BITS && + op != VectorOperators.EXPAND_BITS) + .filter(op -> op.compatibleWith(species.elementType()) == compatible) + .map(op -> new Object[] {species, op})) + .toArray(Object[][]::new); + } + + @Test(dataProvider = "unsupportedOperatorProvider") + public void testUnsupportedOperator(VectorSpecies species, + VectorOperators.Operator op) { + Vector vector = species.zero(); + VectorMask mask = species.maskAll(false); + + switch (op) { + case VectorOperators.Unary unary -> { + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(unary)); + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(unary, mask)); + } + case VectorOperators.Binary binary -> { + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(binary, vector)); + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(binary, 0L)); + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(binary, vector, mask)); + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(binary, 0L, mask)); + } + case VectorOperators.Ternary ternary -> { + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(ternary, vector, vector)); + Assert.assertThrows(UnsupportedOperationException.class, + () -> vector.lanewise(ternary, vector, vector, mask)); + } + default -> throw new AssertionError("Not a lanewise operator: " + op); + } + } + + @Test(dataProvider = "supportedOperatorProvider") + public void testSupportedOperator(VectorSpecies species, + VectorOperators.Operator op) { + Vector vector = species.zero().broadcast(1L); + VectorMask mask = species.maskAll(true); + + switch (op) { + case VectorOperators.Unary unary -> { + vector.lanewise(unary); + vector.lanewise(unary, mask); + } + case VectorOperators.Binary binary -> { + vector.lanewise(binary, vector); + vector.lanewise(binary, 1L); + vector.lanewise(binary, vector, mask); + vector.lanewise(binary, 1L, mask); + } + case VectorOperators.Ternary ternary -> { + vector.lanewise(ternary, vector, vector); + vector.lanewise(ternary, vector, vector, mask); + } + default -> throw new AssertionError("Not a lanewise operator: " + op); + } + } +} diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index f1223f685c0e..0d3d84ecd4f0 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -83,7 +83,7 @@ private static void testLimitUpdates() throws Exception { started.delete(); DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "LimitUpdateChecker"); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); - opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp"); + opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp:z"); opts.addDockerOpts("--cpu-period", Integer.toString(CPU_PERIOD)); opts.addDockerOpts("--cpu-quota", Integer.toString(INITIAL_CPU_COUNT * CPU_PERIOD)); opts.addDockerOpts("--memory", "500m"); diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahEvacuationInformationEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahEvacuationInformationEvent.java index 75fe1ee78846..a75d21d83c5f 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahEvacuationInformationEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahEvacuationInformationEvent.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahPromotionInformationEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahPromotionInformationEvent.java index c315694718b5..6a3c1ba1e567 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahPromotionInformationEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahPromotionInformationEvent.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com Inc. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/jdk/jfr/event/runtime/TestClassDefineEventWithViolatedLoadingConstraints.java b/test/jdk/jdk/jfr/event/runtime/TestClassDefineEventWithViolatedLoadingConstraints.java new file mode 100644 index 000000000000..d588f7b6bbd1 --- /dev/null +++ b/test/jdk/jdk/jfr/event/runtime/TestClassDefineEventWithViolatedLoadingConstraints.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.runtime; + +import java.io.InputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.file.Path; +import java.util.List; +import java.security.CodeSigner; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedClassLoader; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.jfr.TestClassLoader; + +/** + * @test + * @requires vm.flagless + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.event.runtime.TestClassDefineEventWithViolatedLoadingConstraints + */ + +public class TestClassDefineEventWithViolatedLoadingConstraints { + private final static String EVENT_NAME = EventNames.ClassDefine; + private final static String CLASS_NAME = TestClassDefineEventWithViolatedLoadingConstraints.class.getName(); + private final static String DEFINED_CLASS_NAME = CLASS_NAME + "$DuplicateDefinition"; + private final static String FAKE_SOURCE_PATH = "/my/fake/synthetic/classloading/source.jar"; + + static class DuplicateDefinition { } + + static class DuplicateDefinitionClassLoader extends ClassLoader { + DuplicateDefinitionClassLoader() { + super(null); + } + + Class define(byte[] bytes, String classname) throws Exception { + CodeSource cs = null; + try { + Path fakeJar = Path.of("my", "fake", "synthetic", "classloading", "source.jar"); + cs = new CodeSource(fakeJar.toUri().toURL(), (CodeSigner[]) null); + } catch (MalformedURLException ex) { + throw ex; + } + return defineClass(classname, bytes, 0, bytes.length, new ProtectionDomain(cs, null)); + } + } + + private static byte[] readClassBytes(Class clazz) throws IOException { + String resource = clazz.getName().replace('.', '/') + ".class"; + ClassLoader loader = clazz.getClassLoader(); + if (loader != null) { + InputStream in = loader.getResourceAsStream(resource); + if (in == null) { + throw new RuntimeException("Could not find " + clazz.getName()); + } + return in.readAllBytes(); + } + return null; + } + + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EVENT_NAME); + recording.start(); + byte[] duplicateDefBytes = readClassBytes(DuplicateDefinition.class); + DuplicateDefinitionClassLoader loader = new DuplicateDefinitionClassLoader(); + + // First class definition is fine and should result in a jdk.ClassDefine event. + loader.define(duplicateDefBytes, DEFINED_CLASS_NAME); + + try { + // Intentionally violate a class loading constraint by defining the same class + // again with the same class loader. This should throw a java.lang.LinkageError, + // and we should NOT get a jdk.ClassDefine event for this failed attempt. + // + // Most importantly, the JVM should NOT assert or crash as a consequence of JFR + // tagging and enqueuing an InstanceKlass that violates loading constraints. + // Because such an InstanceKlass is immediately put on the class_loader_data's deallocation list, + // it is not registered with a JFR unload set. + // + // Having such an InstanceKlass enqueued is therefore a broken invariant. + loader.define(duplicateDefBytes, DEFINED_CLASS_NAME); + throw new RuntimeException("Expected LinkageError not thrown"); + } catch (LinkageError e) { + // as expected + } finally { + recording.stop(); + } + + validate(recording); + } + } + + private static void validate(Recording recording) throws Exception { + List events = Events.fromRecording(recording); + int numberOfDuplicateDefinitionClassDefinedEvents = 0; + for (RecordedEvent event : events) { + System.out.println(event); + RecordedClassLoader definingClassLoader = event.getValue("definingClassLoader"); + if (definingClassLoader == null) { + continue; + } + RecordedClass classLoader = definingClassLoader.getType(); + if (classLoader == null) { + Asserts.assertTrue("bootstrap".equals(definingClassLoader.getName()), "not the bootstrap class loader?"); + continue; + } + if (DuplicateDefinitionClassLoader.class.getName().equals(classLoader.getName())) { + RecordedClass definedClass = event.getValue("definedClass"); + Asserts.assertNotNull(definedClass, "Defined Class should not be null"); + if (DEFINED_CLASS_NAME.equals(definedClass.getName())) { + Asserts.assertTrue(event.getString("source").startsWith("file://")); + Asserts.assertTrue(event.getString("source").endsWith(FAKE_SOURCE_PATH)); + numberOfDuplicateDefinitionClassDefinedEvents++; + } + } + } + Asserts.assertEquals(1, numberOfDuplicateDefinitionClassDefinedEvents, + "Wrong number of class define event for " + DEFINED_CLASS_NAME + ". Expected 1, got " + numberOfDuplicateDefinitionClassDefinedEvents); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestAssemble.java b/test/jdk/jdk/jfr/tool/TestAssemble.java index 43c862d8999a..4aec19342e16 100644 --- a/test/jdk/jdk/jfr/tool/TestAssemble.java +++ b/test/jdk/jdk/jfr/tool/TestAssemble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,11 @@ import java.io.FileWriter; import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import jdk.jfr.Event; import jdk.jfr.Name; @@ -69,14 +71,16 @@ public static void main(String[] args) throws Throwable { r.stop(); recordings[i] = r; } - Path dir = Paths.get("reconstruction-parts"); + Path dir = Paths.get("reconstruction-parts").toAbsolutePath(); Files.createDirectories(dir); long expectedCount = 0; + Path[] files = new Path[RECORDING_COUNT]; for (int i = 0; i < RECORDING_COUNT; i++) { - Path tmp = dir.resolve("chunk-part-" + i + ".jfr"); - recordings[i].dump(tmp); - expectedCount += countEventInRecording(tmp); + Path file = dir.resolve("chunk-part-" + i + ".jfr"); + recordings[i].dump(file); + expectedCount += countEventInRecording(file); + files[i] = file; } Path repository = Repository.getRepository().getRepositoryPath(); @@ -112,15 +116,50 @@ public static void main(String[] args) throws Throwable { output = ExecuteHelper.jfr("assemble", directory, destination); System.out.println(output.getOutput()); output.shouldContain("Finished."); - long reconstructedCount = countEventInRecording(destinationPath); Asserts.assertEquals(expectedCount, reconstructedCount); + Files.delete(destinationPath); + + // Test unfinished and updated + writeUnfinished(files[1]); + writeUpdating(files[2]); + output = ExecuteHelper.jfr("assemble", dir.toString(), destination); + System.out.println(output.getOutput()); + output.shouldContain("Skipping"); + output.shouldContain("Truncating"); + reconstructedCount = countEventInRecording(destinationPath); + Asserts.assertEquals(RECORDING_COUNT - 1L, reconstructedCount); + Files.delete(destinationPath); + // Cleanup for (int i = 0; i < RECORDING_COUNT; i++) { recordings[i].close(); } } + private static void writeUpdating(Path path) throws IOException { + try (RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw")) { + raf.seek(64); // file state position + raf.write(255); // means the JVM is currently modifying header + appendJunk(raf); + } + } + + private static void writeUnfinished(Path path) throws IOException { + try (RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw")) { + raf.seek(64); // file state position + raf.write(42); // generation 42 (not finished) + appendJunk(raf); + } + } + + private static void appendJunk(RandomAccessFile raf) throws IOException { + byte[] junk = new byte[131072]; + Arrays.fill(junk, (byte)42); + raf.seek(raf.length()); + raf.write(junk); + } + private static long countEventInRecording(Path file) throws IOException { Integer lastId = -1; try (RecordingFile rf = new RecordingFile(file)) { diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java b/test/jdk/jdk/security/JavaDotSecurity/TestLegacyCryptoAlgorithms.java similarity index 53% rename from test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java rename to test/jdk/jdk/security/JavaDotSecurity/TestLegacyCryptoAlgorithms.java index f445f538ea79..762342934344 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java +++ b/test/jdk/jdk/security/JavaDotSecurity/TestLegacyCryptoAlgorithms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,24 +21,23 @@ * questions. */ +import java.security.Security; -/* +/** * @test - * @modules java.base/jdk.internal.misc:+open - * - * @summary converted from VM Testbase metaspace/gc/firstGC_10m. - * VM Testbase keywords: [nonconcurrent, quarantine] - * VM Testbase comments: 8208250 - * - * @library /vmTestbase /test/lib - * @run main/othervm - * -Xms200m - * -Xlog:gc+heap=trace,gc:gc.log - * -XX:MetaspaceSize=10m - * -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions - * -XX:-VerifyBeforeExit - * -XX:-UseCompressedOops - * metaspace.gc.FirstGCTest + * @bug 8388138 + * @summary Test the default setting of the jdk.crypto.legacyAlgorithms security property + * @comment This property has a default value of "Cipher.RSA/ECB/PKCS1Padding" + * This test assures the default is not changed. + * @run main TestLegacyCryptoAlgorithms */ +public class TestLegacyCryptoAlgorithms { + public static void main(String args[]) throws Exception { + String value = Security.getProperty("jdk.crypto.legacyAlgorithms"); + if (value == null || !value.equals("Cipher.RSA/ECB/PKCS1Padding")) { + throw new RuntimeException("Test failed: jdk.crypto.legacyAlgorithms " + + "security property does not have default value of Cipher.RSA/ECB/PKCS1Padding"); + } + } +} diff --git a/test/jdk/sun/net/www/http/HttpClient/IsAvailable.java b/test/jdk/sun/net/www/http/HttpClient/IsAvailable.java index 65752737c628..072a58022f7b 100644 --- a/test/jdk/sun/net/www/http/HttpClient/IsAvailable.java +++ b/test/jdk/sun/net/www/http/HttpClient/IsAvailable.java @@ -67,6 +67,7 @@ import org.junit.jupiter.api.Test; import sun.net.www.http.HttpClient; +import java.util.function.Function; import java.util.function.Predicate; import java.util.logging.ConsoleHandler; import java.util.logging.Level; @@ -117,6 +118,13 @@ void testClosedSocket() throws Exception { // Verify that closing the socket removes the availability LOGGER.info("Closing the socket..."); infra.clientSocket.close(); + // Closing the server socket may not immediately be observable by + // the client. Read from the client's _internal_ socket to ensure + // that EOF, which is necessary for the `HttpClient::available` + // verification, has arrived. + assertEquals( + -1, infra.readFromHttpClientSocket(), + "Expected EOF after closing the server socket"); LOGGER.info("Checking the connection (#2)..."); assertFalse(infra.available(), "Connection over closed socket should not be available"); assertEquals(readTimeout, infra.httpClient.getReadTimeout(), "Read-timeout should be restored"); @@ -142,10 +150,13 @@ void testSocketWithUnconsumedData() throws Exception { clientSocketOutputStream.write("unexpected data".getBytes(US_ASCII)); } - // Writing to the socket on the server side may not make the data - // immediately visible to the client side. Make sure we wait long - // enough for the data to get delivered. - Thread.sleep(adjustTimeout(500)); + // Writing to the server socket may not immediately be observable + // by the client. Read from the client's _internal_ socket to ensure + // that the data, which is necessary for the `HttpClient::available` + // verification, has arrived. + assertTrue( + infra.readFromHttpClientSocket() >= 0, + "Unexpected data should have arrived to the client socket"); // Verify that the presence of stale data on the socket removes the availability LOGGER.info("Checking the connection (#2)..."); @@ -161,6 +172,8 @@ private static final class Infra implements Closeable { private static final Predicate AVAILABLE_ACCESSOR = findAvailableAccessor(); + private static final Function SERVER_SOCKET_ACCESSOR = findServerSocketAccessor(); + private static Predicate findAvailableAccessor() { final MethodHandle availableMH; try { @@ -179,6 +192,24 @@ private static Predicate findAvailableAccessor() { }; } + private static Function findServerSocketAccessor() { + final MethodHandle serverSocketMH; + try { + serverSocketMH = MethodHandles + .privateLookupIn(HttpClient.class, MethodHandles.lookup()) + .findGetter(HttpClient.class, "serverSocket", Socket.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + return httpClient -> { + try { + return (Socket) serverSocketMH.invoke(httpClient); + } catch (Throwable e) { + throw new RuntimeException(e); + } + }; + } + private final ServerSocket serverSocket; private final HttpClient httpClient; @@ -210,6 +241,17 @@ private boolean available() { return AVAILABLE_ACCESSOR.test(httpClient); } + private int readFromHttpClientSocket() throws IOException { + Socket socket = SERVER_SOCKET_ACCESSOR.apply(httpClient); + int timeout = socket.getSoTimeout(); + try { + socket.setSoTimeout((int) adjustTimeout(5000)); + return socket.getInputStream().read(); + } finally { + socket.setSoTimeout(timeout); + } + } + @Override public void close() { closeQuietly("client socket", clientSocket); diff --git a/test/jdk/sun/security/ec/NONEwithECDSAOffsetTest.java b/test/jdk/sun/security/ec/NONEwithECDSAOffsetTest.java new file mode 100644 index 000000000000..c4a76b2f2767 --- /dev/null +++ b/test/jdk/sun/security/ec/NONEwithECDSAOffsetTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * 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.nio.ByteBuffer; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.util.Arrays; + +import jtreg.SkippedException; + +/* + * @test + * @bug 8385672 + * @summary This test validates the length checks in SunEC's NONEwithECDSA + * implementation + * @library /test/lib/ + */ + +public class NONEwithECDSAOffsetTest { + + private static Signature s; + private static PrivateKey pk; + + public static void main(String[] args) throws Exception { + Provider prov = Security.getProvider("SunEC"); + if (prov == null) { + throw new SkippedException("Skip test - no SunEC provider found"); + } + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", prov); + kpg.initialize(new ECGenParameterSpec("secp521r1")); + pk = kpg.generateKeyPair().getPrivate(); + s = Signature.getInstance("NONEwithECDSA", prov); + + test(48, true); + test(64, true); + test(65, false); + } + + private static void test(int dataLen, boolean shouldPass) throws Exception { + System.out.println("Testing " + dataLen + ", shouldPass = " + + shouldPass); + byte[] data = new byte[dataLen]; + Arrays.fill(data, (byte) dataLen); + + int testNum = 1; + boolean done = false; + while (!done) { + String testId = String.format("Test#%d", testNum); + s.initSign(pk); + try { + switch (testNum++) { + case 1: // update(byte) + byte i = 0; + while (i++ < dataLen) { + s.update(i); + } + break; + case 2: // update(byte[]) + s.update(data); + break; + case 3: // update(byte[], int, int) + int firstPart = data.length/2; + s.update(data, 0, firstPart); + s.update(data, firstPart, data.length - firstPart); + break; + case 4: // update(ByteBuffer) + s.update(ByteBuffer.wrap(data)); + done = true; + break; + default: + throw new AssertionError("Error: Unsupported testNum" + + testNum); + } + s.sign(); + if (!shouldPass) { + done = true; + throw new AssertionError(testId + + " should throw SignatureException"); + } + } catch (SignatureException se) { + if (shouldPass) { + done = true; + throw new AssertionError(testId + + ": Unexpected SignatureException", se); + } + } + } + } +} diff --git a/test/jdk/sun/security/internal/CheckIBE.java b/test/jdk/sun/security/internal/CheckIBE.java index 802cd336ebc3..8e38c0d4ddcb 100644 --- a/test/jdk/sun/security/internal/CheckIBE.java +++ b/test/jdk/sun/security/internal/CheckIBE.java @@ -25,7 +25,6 @@ * @test * @bug 8383608 * @summary check that InternalBinaryEncodable exists - * @enablePreview * @modules java.base/sun.security.internal * @run main CheckIBE */ diff --git a/test/jdk/sun/security/internal/ExhaustiveBE.java b/test/jdk/sun/security/internal/ExhaustiveBE.java index 37222a0310ab..370ff58c28d8 100644 --- a/test/jdk/sun/security/internal/ExhaustiveBE.java +++ b/test/jdk/sun/security/internal/ExhaustiveBE.java @@ -25,7 +25,6 @@ * @test * @bug 8383608 * @summary verify switches over BinaryEncodable are not exhaustive - * @enablePreview * @compile/fail ExhaustiveBE.java */ diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java b/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java index 0e8cb36659f8..27a1073e4a40 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Red Hat, Inc. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,6 +34,9 @@ import javax.crypto.Cipher; import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; /* @@ -60,7 +64,9 @@ public final class ImportKeyToP12 extends PKCS11Test { }; private static final String[] pbeMacAlgs = new String[] { "HmacPBESHA1", "HmacPBESHA224", "HmacPBESHA256", - "HmacPBESHA384", "HmacPBESHA512" + "HmacPBESHA384", "HmacPBESHA512", "PBEWithHmacSHA1", + "PBEWithHmacSHA224", "PBEWithHmacSHA256", "PBEWithHmacSHA384", + "PBEWithHmacSHA512" }; private static final KeyStore p12; private static final String sep = "======================================" + @@ -74,6 +80,14 @@ public final class ImportKeyToP12 extends PKCS11Test { p12 = tP12; } + private record PBMAC1Algorithms(String pbkdf2, String hmac) {} + + private static PBMAC1Algorithms pbmac1Algorithms(String algorithm) { + // PBMAC1 algorithms with matching PBKDF2 PRF and HMAC names. + String hmac = algorithm.substring("PBEWith".length()); + return new PBMAC1Algorithms("PBKDF2With" + hmac, hmac); + } + public void main(Provider sunPKCS11) throws Exception { System.out.println("SunPKCS11: " + sunPKCS11.getName()); // Test all privacy PBE algorithms with an integrity algorithm fixed @@ -84,8 +98,25 @@ public void main(Provider sunPKCS11) throws Exception { } // Test all integrity PBE algorithms with a privacy algorithm fixed for (String pbeMacAlg : pbeMacAlgs) { - // Make sure that SunPKCS11 implements the Mac algorithm - Mac.getInstance(pbeMacAlg, sunPKCS11); + // Verify the PBKDF2/HMAC components needed for PBMAC1 are present + if (pbeMacAlg.startsWith("PBEWith")) { + byte[] salt = { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 }; + + PBMAC1Algorithms algorithms = pbmac1Algorithms(pbeMacAlg); + Mac m = Mac.getInstance(algorithms.hmac(), sunPKCS11); + int keyLength = m.getMacLength() * Byte.SIZE; + SecretKeyFactory skf = SecretKeyFactory.getInstance( + algorithms.pbkdf2(), sunPKCS11); + PBEKeySpec keySpec = new PBEKeySpec(password, + salt, 10000, keyLength); + + SecretKey pbeKey = skf.generateSecret(keySpec); + m.init(pbeKey); + m.doFinal(); + } else { + Mac.getInstance(pbeMacAlg, sunPKCS11); + } testWith(sunPKCS11, pbeCipherAlgs[0], pbeMacAlg); } System.out.println("TEST PASS - OK"); diff --git a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java index eee55998f0bc..c29f7a0b11db 100644 --- a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java +++ b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,8 +182,8 @@ private static void testWithJavaCommands() throws Throwable { + "-destkeystore ksnormal -deststorepass changeit"); data = Files.readAllBytes(Path.of("ksnormal")); - checkInt(data, "22", 10000); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 10000); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 10000); // key ic checkAlg(data, "110c10", ENCRYPTED_DATA_OID); @@ -210,8 +210,8 @@ private static void testWithJavaCommands() throws Throwable { + "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE " + "-J-Dkeystore.pkcs12.macAlgorithm=NONE"); data = Files.readAllBytes(Path.of("ksnormal")); - checkInt(data, "22", 10000); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 10000); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 10000); // key ic checkAlg(data, "110c010c11000", PBES2); // new key alg @@ -255,8 +255,8 @@ private static void testWithJavaCommands() throws Throwable { + "-J-Dkeystore.pkcs12.certPbeIterationCount=6666 " + "-J-Dkeystore.pkcs12.keyPbeIterationCount=7777"); data = Files.readAllBytes(Path.of("ksnewic")); - checkInt(data, "22", 5555); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 5555); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 7777); // key ic checkAlg(data, "110c110110", PBES2); // cert alg @@ -274,8 +274,8 @@ private static void testWithJavaCommands() throws Throwable { + "-storepass changeit -alias b -dname CN=B " + "-J-Dkeystore.pkcs12.keyProtectionAlgorithm=PBEWithSHA1AndRC4_128"); data = Files.readAllBytes(Path.of("ksnewic")); - checkInt(data, "22", 5555); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 5555); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 7777); // key ic checkAlg(data, "110c010c11000", PBEWithSHA1AndRC4_128); // new key alg @@ -291,8 +291,8 @@ private static void testWithJavaCommands() throws Throwable { ks.store(fos, "changeit".toCharArray()); } data = Files.readAllBytes(Path.of("ksnormaldup")); - checkInt(data, "22", 10000); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 10000); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 10000); // key ic checkAlg(data, "110c010c11000", PBES2); // new key alg @@ -320,8 +320,8 @@ private static void testWithJavaCommands() throws Throwable { ks.store(fos, "changeit".toCharArray()); } data = Files.readAllBytes(Path.of("ksnewicdup")); - checkInt(data, "22", 5555); // Mac ic - checkAlg(data, "2000", SHA_256); // Mac alg + checkInt(data, "2001011", 5555); // Mac ic + checkAlg(data, "2000", PBMAC1); // Mac alg checkAlg(data, "110c010c01000", PBES2); // key alg checkInt(data, "110c010c01001011", 7777); // key ic checkAlg(data, "110c010c11000", PBEWithSHA1AndRC4_128); // new key alg @@ -476,7 +476,7 @@ private static void testWithOpensslCommands(String opensslPath) "pkcs12", "-in", "ksnormal", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldMatch("MAC:.*sha256.*Iteration 10000") + .shouldMatch("MAC:.*PBMAC1.*Iteration 10000") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 10000, PRF hmacWithSHA256") .shouldContain("PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC," @@ -521,7 +521,7 @@ private static void testWithOpensslCommands(String opensslPath) "ksnewic", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldMatch("MAC:.*sha256.*Iteration 5555") + .shouldMatch("MAC:.*PBMAC1.*Iteration 5555") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 7777, PRF hmacWithSHA256") .shouldContain("Shrouded Keybag: pbeWithSHA1And128BitRC4," diff --git a/test/jdk/sun/security/pkcs12/ParamsPreferences.java b/test/jdk/sun/security/pkcs12/ParamsPreferences.java index c40bd4f4b705..47b1e07891e5 100644 --- a/test/jdk/sun/security/pkcs12/ParamsPreferences.java +++ b/test/jdk/sun/security/pkcs12/ParamsPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ public static final void main(String[] args) throws Exception { Map.of(), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, - SHA_256, 10000); + PBMAC1, 10000); // legacy settings test(c++, @@ -116,7 +116,33 @@ public static final void main(String[] args) throws Exception { "keystore.pkcs12.macAlgorithm", "NONE"), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, - SHA_256, 10000); + PBMAC1, 10000); + + // configure PBMAC1 MAC with system property + test(c++, + Map.of("keystore.pkcs12.certProtectionAlgorithm", "PBEWithSHA1AndDESede", + "keystore.pkcs12.certPbeIterationCount", 3000, + "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_40", + "keystore.pkcs12.keyPbeIterationCount", 4000, + "keystore.pkcs12.macAlgorithm", "PBEWithHmacSHA256", + "keystore.pkcs12.macIterationCount", 2000), + Map.of(), + PBEWithSHA1AndDESede, 3000, + PBEWithSHA1AndRC2_40, 4000, + PBMAC1, 2000); + + // configure PBMAC1 MAC with security property + test(c++, + Map.of(), + Map.of("keystore.pkcs12.certProtectionAlgorithm", "PBEWithSHA1AndDESede", + "keystore.pkcs12.certPbeIterationCount", 3000, + "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_40", + "keystore.pkcs12.keyPbeIterationCount", 4000, + "keystore.pkcs12.macAlgorithm", "PBEWithHmacSHA256", + "keystore.pkcs12.macIterationCount", 2000), + PBEWithSHA1AndDESede, 3000, + PBEWithSHA1AndRC2_40, 4000, + PBMAC1, 2000); // change everything with system property test(c++, @@ -170,21 +196,21 @@ public static final void main(String[] args) throws Exception { Map.of("keystore.PKCS12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_128"), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBEWithSHA1AndRC2_128, 10000, - SHA_256, 10000); + PBMAC1, 10000); test(c++, Map.of(), Map.of("keystore.PKCS12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_128", "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_40"), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBEWithSHA1AndRC2_40, 10000, - SHA_256, 10000); + PBMAC1, 10000); test(c++, Map.of("keystore.PKCS12.keyProtectionAlgorithm", "PBEWithSHA1AndRC4_128"), Map.of("keystore.PKCS12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_128", "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_40"), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBEWithSHA1AndRC4_128, 10000, - SHA_256, 10000); + PBMAC1, 10000); test(c++, Map.of("keystore.PKCS12.keyProtectionAlgorithm", "PBEWithSHA1AndRC4_128", "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC4_40"), @@ -192,7 +218,7 @@ public static final void main(String[] args) throws Exception { "keystore.pkcs12.keyProtectionAlgorithm", "PBEWithSHA1AndRC2_40"), PBES2, HmacSHA256, AES_256$CBC$NoPadding, 10000, PBEWithSHA1AndRC4_40, 10000, - SHA_256, 10000); + PBMAC1, 10000); // 8266293 test(c++, @@ -201,7 +227,7 @@ public static final void main(String[] args) throws Exception { Map.of(), PBEWithMD5AndDES, 10000, PBEWithMD5AndDES, 10000, - SHA_256, 10000); + PBMAC1, 10000); } /** @@ -269,6 +295,9 @@ static void test(int n, Map sysProps, KnownOIDs macAlg = (KnownOIDs)args[i++]; if (macAlg == null) { shouldNotExist(data, "2"); + } else if (macAlg.stdName().equals("PBMAC1")) { + checkAlg(data, "2000", macAlg); + checkInt(data, "2001011", (int) args[i++]); } else { checkAlg(data, "2000", macAlg); checkInt(data, "22", (int) args[i++]); diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java index 9c68ae138ef7..54d96a1f1338 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java @@ -29,7 +29,6 @@ * * @bug 6861062 * @summary Disable MD2 support - * @enablePreview * * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_1024 0 true * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_512 0 true diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java index cbdeb6609e42..2a008d4a34a2 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java @@ -29,7 +29,6 @@ * * @bug 8030829 * @summary Add MD5 to jdk.certpath.disabledAlgorithms security property - * @enablePreview * * @run main/othervm CPBuilderWithMD5 trustAnchor_SHA1withRSA_1024 0 true * @run main/othervm CPBuilderWithMD5 trustAnchor_SHA1withRSA_512 0 true diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java index aa19bc2f0c83..4715f3aadf68 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ * @summary Disable MD2 support. * New CertPathValidatorException.BasicReason enum constant for * constrained algorithm. - * @enablePreview * @run main/othervm CPValidatorEndEntity * @author Xuelei Fan */ diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java index 72dff1694b1c..ca5132e63fd7 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ * @summary Disable MD2 support * new CertPathValidatorException.BasicReason enum constant for * constrained algorithm - * @enablePreview * @run main/othervm CPValidatorIntermediate * @author Xuelei Fan */ diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java index d74d712d8d74..80173d7e2b36 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ * @summary Disable MD2 support * new CertPathValidatorException.BasicReason enum constant for * constrained algorithm - * @enablePreview * @run main/othervm CPValidatorTrustAnchor * @author Xuelei Fan */ diff --git a/test/jdk/sun/security/rsa/InvalidBitString.java b/test/jdk/sun/security/rsa/InvalidBitString.java index 7f8408f35f0b..53fabc50bbb3 100644 --- a/test/jdk/sun/security/rsa/InvalidBitString.java +++ b/test/jdk/sun/security/rsa/InvalidBitString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ /* @test * @summary Validation of signatures succeed when it should fail - * @enablePreview * @bug 6896700 */ diff --git a/test/jdk/sun/security/rsa/pss/PSSKeyCompatibility.java b/test/jdk/sun/security/rsa/pss/PSSKeyCompatibility.java index 49ee7387f177..61701a686faa 100644 --- a/test/jdk/sun/security/rsa/pss/PSSKeyCompatibility.java +++ b/test/jdk/sun/security/rsa/pss/PSSKeyCompatibility.java @@ -44,7 +44,6 @@ * @test * @bug 8242335 * @summary OpenSSL generated compatibility test with RSASSA-PSS Java. - * @enablePreview * @run main PSSKeyCompatibility */ diff --git a/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java b/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java index 26d5c69e2198..ffa4724f98c6 100644 --- a/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java +++ b/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ /* * @test * @bug 6690018 - * @enablePreview * @summary RSAClientKeyExchange NullPointerException * @run main/othervm RSAExport */ diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java index 051c940b3b08..ddf27ab71b20 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ * @bug 7166570 * @summary JSSE certificate validation has started to fail for * certificate chains - * @enablePreview * @run main/othervm BasicConstraints PKIX * @run main/othervm BasicConstraints SunX509 */ diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java index f1e5415e2c3b..974ac870e06a 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 7123519 * @summary Problem with java/classes_security - * @enablePreview * @run main/othervm ComodoHacker PKIX * @run main/othervm ComodoHacker SunX509 */ diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java index 287dbcc2b025..e3422c4955c3 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java @@ -30,7 +30,6 @@ * @test * @bug 6916074 8170131 * @summary Add support for TLS 1.2 - * @enablePreview * @run main/othervm PKIXExtendedTM 0 * @run main/othervm PKIXExtendedTM 1 * @run main/othervm PKIXExtendedTM 2 diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java index a742b0b8a72c..fdb46c49e501 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java @@ -30,7 +30,6 @@ * @test * @bug 6916074 * @summary Add support for TLS 1.2 - * @enablePreview * @run main/othervm SunX509ExtendedTM */ diff --git a/test/jdk/sun/security/validator/PKIXValAndRevCheckTests.java b/test/jdk/sun/security/validator/PKIXValAndRevCheckTests.java index 883d79057ebb..9a9601451990 100644 --- a/test/jdk/sun/security/validator/PKIXValAndRevCheckTests.java +++ b/test/jdk/sun/security/validator/PKIXValAndRevCheckTests.java @@ -27,7 +27,6 @@ * @summary Stapled OCSPResponses should be added to PKIXRevocationChecker * irrespective of revocationEnabled flag * @library /test/lib - * @enablePreview * @modules java.base/sun.security.validator * @build jdk.test.lib.Convert * @run main PKIXValAndRevCheckTests diff --git a/test/jdk/sun/security/x509/X509CRLImpl/Verify.java b/test/jdk/sun/security/x509/X509CRLImpl/Verify.java index a10a18971d20..6f81ef5bd435 100644 --- a/test/jdk/sun/security/x509/X509CRLImpl/Verify.java +++ b/test/jdk/sun/security/x509/X509CRLImpl/Verify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 7026347 * @summary X509CRL should have verify(PublicKey key, Provider sigProvider) - * @enablePreview */ import java.security.InvalidKeyException; diff --git a/test/jdk/tools/jlink/JLinkToolProviderTest.java b/test/jdk/tools/jlink/JLinkToolProviderTest.java index 94959dcc8d80..ba9eab5c9314 100644 --- a/test/jdk/tools/jlink/JLinkToolProviderTest.java +++ b/test/jdk/tools/jlink/JLinkToolProviderTest.java @@ -34,7 +34,7 @@ /* * @test * @modules jdk.jlink - * @run main JLinkToolProviderTest + * @run main/othervm JLinkToolProviderTest */ public class JLinkToolProviderTest { static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java index 0701421e999f..0f56d6dbd124 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,8 @@ public record ApplicationLayout(Path launchersDirectory, Path appDirectory, Path runtimeDirectory, Path runtimeHomeDirectory, Path appModsDirectory, - Path desktopIntegrationDirectory, Path contentDirectory, Path libapplauncher) { + Path desktopIntegrationDirectory, Path contentDirectory, Path resourcesDirectory, + Path libapplauncher) { public ApplicationLayout resolveAt(Path root) { return new ApplicationLayout( @@ -40,6 +41,7 @@ public ApplicationLayout resolveAt(Path root) { resolve(root, appModsDirectory), resolve(root, desktopIntegrationDirectory), resolve(root, contentDirectory), + resolve(root, resourcesDirectory), resolve(root, libapplauncher)); } @@ -52,6 +54,7 @@ public static ApplicationLayout linuxAppImage() { Path.of("lib/app/mods"), Path.of("lib"), Path.of("lib"), + Path.of("lib"), Path.of("lib/libapplauncher.so") ); } @@ -65,6 +68,7 @@ public static ApplicationLayout windowsAppImage() { Path.of("app/mods"), Path.of(""), Path.of(""), + Path.of(""), null ); } @@ -78,6 +82,7 @@ public static ApplicationLayout macAppImage() { Path.of("Contents/app/mods"), Path.of("Contents/Resources"), Path.of("Contents"), + Path.of("Contents/Resources"), null ); } @@ -113,6 +118,7 @@ public static ApplicationLayout platformJavaRuntime() { null, null, null, + null, null ); } @@ -128,6 +134,7 @@ public static ApplicationLayout linuxUsrTreePackageImage(Path prefix, lib.resolve("app/mods"), lib, lib, + lib, lib.resolve("lib/libapplauncher.so") ); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 733a087fe683..25b1c3a9784f 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -1012,6 +1012,14 @@ public JPackageCommand setEnabledMessageCategories(MessageCategory... categories return setEnabledMessageCategories(Set.of(categories)); } + public JPackageCommand enableMessageCategories(Set categories) { + return setEnabledMessageCategories(SetBuilder.build(logConfig.add()).add(categories).emptyAllowed(true).create()); + } + + public JPackageCommand enableMessageCategories(MessageCategory... categories) { + return enableMessageCategories(Set.of(categories)); + } + public JPackageCommand setDisabledMessageCategories(Set categories) { verifyMutable(); logConfig = new LogConfig( @@ -1024,6 +1032,14 @@ public JPackageCommand setDisabledMessageCategories(MessageCategory... categorie return setDisabledMessageCategories(Set.of(categories)); } + public JPackageCommand disableMessageCategories(Set categories) { + return setDisabledMessageCategories(SetBuilder.build(logConfig.remove()).add(categories).emptyAllowed(true).create()); + } + + public JPackageCommand disableMessageCategories(MessageCategory... categories) { + return disableMessageCategories(Set.of(categories)); + } + public static Set messageCategoriesConsoleAll() { return Stream.of(MessageCategory.values()).filter(MessageCategory::isConsole).collect(toSet()); } @@ -1508,6 +1524,7 @@ public static enum ReadOnlyPathAssert { return !(TKit.isOSX() && MacHelper.signPredefinedAppImage(cmd)); }).create()), APP_CONTENT(new Builder("--app-content").multiple().create()), + APP_RESOURCES(new Builder("--app-resources").multiple().create()), RESOURCE_DIR(new Builder("--resource-dir").create()), MAC_DMG_CONTENT(new Builder("--mac-dmg-content").multiple().create()), RUNTIME_IMAGE(new Builder("--runtime-image").create()); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageOutputValidator.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageOutputValidator.java index 8817ca0b7300..72a02362598a 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageOutputValidator.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageOutputValidator.java @@ -130,7 +130,7 @@ public JPackageOutputValidator matchTimestamps() { *

* If the stream contains lines without timestampts, the validation will fail. *

- * Use {@link #matchTimestamps()) to filter out lines without timestamps and + * Use {@link #matchTimestamps()} to filter out lines without timestamps and * prevent validation failure. * * @return this diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index dc8d79ca8411..dd248f67d69b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -24,6 +24,7 @@ import static java.util.Collections.unmodifiableSortedSet; import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import static jdk.jpackage.internal.util.MemoizingSupplier.runOnce; @@ -54,6 +55,7 @@ import jdk.jpackage.internal.util.PathUtils; import jdk.jpackage.internal.util.Result; import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.LauncherShortcut.InvokeShortcutSpec; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -93,6 +95,10 @@ public static Path getDesktopFile(JPackageCommand cmd, String launcherName) { desktopFileName); } + public static boolean isDesktopFileValidateCommandAvailable() { + return DesktopFileValidateAvailable.VALUE; + } + static Path getServiceUnitFilePath(JPackageCommand cmd, String launcherName) { cmd.verifyIsOfType(PackageType.LINUX); return cmd.pathToUnpackedPackageFile( @@ -434,6 +440,11 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, boolean integr "Check there are no .desktop files in the package"); } }); + + test.addInitializer(cmd -> { + cmd.enableMessageCategories(MessageCategory.TOOLS); + verifyDesktopFileValidateInvocationsInOutput(cmd, integrated); + }); } static void verifyDesktopIntegrationFiles(JPackageCommand cmd, boolean installed) { @@ -568,7 +579,8 @@ private static void verifyDesktopFile(JPackageCommand cmd, Optional { + var validatedDesktopEntryFiles = result.stdout().stream() + .filter(JPackageCommand::withTimestamp) + .map(JPackageCommand::stripTimestamp) + .mapMulti((str, sink) -> { + if (str.startsWith(startsWith)) { + sink.accept(Path.of(unquoteIfNeeded(str.substring(startsWith.length())))); + } + }).collect(toCollection(ArrayList::new)); + + if (cmd.hasArgument("--linux-menu-group")) { + TKit.assertTrue(!validatedDesktopEntryFiles.isEmpty(), + "Check that there are traces of desktop-file-validate executions in the output"); + TKit.assertEquals("probe.desktop", validatedDesktopEntryFiles.getFirst().getFileName().toString(), + "Check the name of the file used in the first desktop-file-validate execution"); + validatedDesktopEntryFiles.remove(0); + } + + if (!integrated) { + TKit.assertEquals(List.of(), validatedDesktopEntryFiles, + "Check there are no unexpected traces of desktop-file-validate executions in the output"); + return; + } + + if (!isDesktopFileValidateCommandAvailable()) { + int expectedCount; + if (cmd.hasArgument("--linux-menu-group")) { + expectedCount = 0; + } else { + expectedCount = 1; + } + + TKit.assertEquals(expectedCount, validatedDesktopEntryFiles.size(), + String.format( + "Check that the remaining number of traces of desktop-file-validate executions %s in the output is as expected", + validatedDesktopEntryFiles)); + return; + } + + final List expectedValidatedDesktopEntryFileNames; + if (integrated) { + getDesktopFile(cmd, null); + var launcherDesktopEntryFilenames = cmd.launcherNames(true).stream().map(launcherName -> { + return getLauncherDesktopFileName(cmd, launcherName); + }).toList(); + expectedValidatedDesktopEntryFileNames = getDesktopFiles(cmd).stream() + .map(Path::getFileName) + .filter(launcherDesktopEntryFilenames::contains) + .toList(); + } else { + expectedValidatedDesktopEntryFileNames = List.of(); + } + + var missing = expectedValidatedDesktopEntryFileNames.stream().filter(fileName -> { + return validatedDesktopEntryFiles.stream().map(Path::getFileName).filter(Predicate.isEqual(fileName)).findAny().isEmpty(); + }).sorted().toList(); + + var unexpected = validatedDesktopEntryFiles.stream().filter(path -> { + return !expectedValidatedDesktopEntryFileNames.contains(path.getFileName()); + }).sorted().toList(); + + TKit.assertEquals(List.of(), missing, "Check there are no missing traces of desktop-file-validate executions in the output"); + TKit.assertEquals(List.of(), unexpected, "Check there are no unexpected traces of desktop-file-validate executions in the output"); + }); + } + + private static String unquoteIfNeeded(String str) { + if (str.length() < 2) { + return str; + } + + int startIdx = str.charAt(0) == '\'' ? 1 : 0; + int endIdx = str.charAt(str.length() - 1) == '\'' ? str.length() - 1 : str.length(); + return str.substring(startIdx, endIdx); + } + static void initFileAssociationsTestFile(Path testFile) { try { // Write something in test file. @@ -973,15 +1073,19 @@ private static final class NativePackageType { static final PackageType VALUE; private static boolean isDebian() { - // we are just going to run "dpkg -s coreutils" and assume Debian - // or derivative if no error is returned. - return Result.of(Executor.of("dpkg", "-s", "coreutils")::execute).hasValue(); + // Run "dpkg -s coreutils" command and assume this is native Debian-based Linux if it succeeds. + // If it fails to execute (command not found) or exits with an error (non-zero exit code), we assume the opposite. + return Result.of(Executor.of("dpkg", "-s", "coreutils")::executeWithoutExitCodeCheck).value().filter(result -> { + return result.getExitCode() == 0; + }).isPresent(); } private static boolean isRpm() { - // we are just going to run "rpm -q rpm" and assume RPM - // or derivative if no error is returned. - return Result.of(Executor.of("rpm", "-q", "rpm")::execute).hasValue(); + // Run "rpm -q rpm" command and assume this is native RPM-based Linux if it succeeds. + // If it fails to execute (command not found) or exits with an error (non-zero exit code), we assume the opposite. + return Result.of(Executor.of("rpm", "-q", "rpm")::executeWithoutExitCodeCheck).value().filter(result -> { + return result.getExitCode() == 0; + }).isPresent(); } static { @@ -995,6 +1099,11 @@ private static boolean isRpm() { } } + private static final class DesktopFileValidateAvailable { + + static final boolean VALUE = Result.of(Executor.of("desktop-file-validate", "-h")::executeWithoutExitCodeCheck).hasValue(); + } + private static final Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); // Values grabbed from https://linux.die.net/man/1/xdg-icon-resource diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/ScriptSpec.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/ScriptSpec.java index 60e5723e9a71..e51efb57825e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/ScriptSpec.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/ScriptSpec.java @@ -165,10 +165,6 @@ public Builder add(CommandMockSpec mockSpec) { return build(mockSpec).add(); } - public Builder addLoop(CommandMockSpec mockSpec) { - return build(mockSpec).add(); - } - public ItemBuilder build(CommandMockSpec mockSpec) { return new ItemBuilder(mockSpec); } diff --git a/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryFileValidatorTest.java b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryFileValidatorTest.java new file mode 100644 index 000000000000..09c7bfb97944 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryFileValidatorTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import java.nio.file.Path; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.test.mock.CommandActionSpec; +import jdk.jpackage.test.mock.CommandActionSpecs; +import jdk.jpackage.test.mock.CommandMockExit; +import jdk.jpackage.test.mock.ToolProviderCommandMock; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +class DesktopEntryFileValidatorTest { + + @ParameterizedTest + @EnumSource(value = CommandMockExit.class) + void test_createDefault(CommandMockExit exit) { + + var validator = DesktopEntryFileValidator.createDefault(); + + var counter = new AtomicInteger(); + + ThrowingRunnable incremeter = counter::getAndIncrement; + + ToolProviderCommandMock desktop_file_validate = CommandActionSpecs.build() + .action(CommandActionSpec.create("increment counter", incremeter)) + .exit(exit) + .toCommandMockBuilder().name("desktop-file-validate-mock").create(); + + final int validateCount = 10; + + Globals.main(() -> { + Globals.instance().executorFactory(() -> { + return new Executor().mapper(executor -> { + return executor.copy().mapper(null).toolProvider(desktop_file_validate); + }); + }); + + IntStream.range(0, validateCount).forEach(_ -> { + var result = validator.validate(Path.of("foo.desktop")); + switch (exit) { + case SUCCEED -> assertEquals(0, result.getExitCode()); + case EXIT_1 -> assertEquals(1, result.getExitCode()); + case THROW_MOCK_IO_EXCEPTION -> assertThrowsExactly(IllegalStateException.class, result::getExitCode); + } + }); + + switch (exit) { + case SUCCEED, EXIT_1 -> assertEquals(validateCount, counter.get()); + case THROW_MOCK_IO_EXCEPTION -> assertEquals(1, counter.get()); + } + + return 0; + }); + } +} diff --git a/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryTest.java b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryTest.java new file mode 100644 index 000000000000..d9fd723c3535 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/DesktopEntryTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class DesktopEntryTest { + + @ParameterizedTest + @CsvSource({ + "MIME_TYPE,MimeType", + "NAME,Name", + "COMMENT,Comment", + "EXEC,Exec", + "PATH,Path", + "ICON,Icon", + "TERMINAL,Terminal", + "TYPE,Type", + "CATEGORIES,Categories", + }) + void test_entryKey(DesktopEntry entry, String expectedKey) { + assertEquals(expectedKey, entry.entryKey()); + } + + @ParameterizedTest + @CsvSource({ + "MIME_TYPE,,", + "MIME_TYPE,foo,foo;", + "MIME_TYPE,foo;,foo;", + "MIME_TYPE,'',;", + + "NAME,,", + "NAME,Hello Duke!,Hello Duke!", + "NAME,'',''", + + "COMMENT,,", + "COMMENT,Hello Duke!,Hello Duke!", + "COMMENT,'',''", + + "EXEC,,", + "EXEC,foo/bar,foo/bar", + "EXEC,Hello Duke!,\"Hello Duke!\"", + "EXEC,'',''", + + "PATH,,", + "PATH,foo/bar,foo/bar", + "PATH,Hello Duke!,Hello Duke!", + "PATH,'',''", + + "ICON,,", + "ICON,Hello Duke!,Hello Duke!", + "ICON,'',''", + + "TERMINAL,,", + "TERMINAL,Hello Duke!,Hello Duke!", + "TERMINAL,'',''", + + "TYPE,,", + "TYPE,Hello Duke!,Hello Duke!", + "TYPE,'',''", + + "CATEGORIES,,", + "CATEGORIES,foo,foo;", + "CATEGORIES,foo;,foo;", + "CATEGORIES,'',;", + }) + void test_formatDesktopFileEntryValue(DesktopEntry entry, String entryValue, String expectedFormattedValue) { + + if (entryValue != null) { + assertEquals(expectedFormattedValue, entry.formatDesktopFileEntryValue(entryValue)); + + assertEquals(entry.entryKey() + "=" + expectedFormattedValue, entry.formatDesktopFileEntry(entryValue)); + } else { + assertThrowsExactly(NullPointerException.class, () -> { + entry.formatDesktopFileEntryValue(entryValue); + }); + + assertThrowsExactly(NullPointerException.class, () -> { + entry.formatDesktopFileEntry(entryValue); + }); + } + } +} diff --git a/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxDebPackagerTest.java b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxDebPackagerTest.java new file mode 100644 index 000000000000..e375ea66e8ce --- /dev/null +++ b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxDebPackagerTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + +import static jdk.jpackage.internal.model.StandardPackageType.LINUX_DEB; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import jdk.jpackage.internal.PackagingPipeline.PackageTaskID; +import jdk.jpackage.internal.model.RuntimeLayout; +import jdk.jpackage.internal.util.CommandOutputControl.UnexpectedExitCodeException; +import jdk.jpackage.internal.util.CommandOutputControl.UnexpectedResultException; +import jdk.jpackage.internal.util.Result; +import jdk.jpackage.internal.util.RetryExecutor; +import jdk.jpackage.internal.util.function.ExceptionBox; +import jdk.jpackage.test.mock.CommandActionSpecs; +import jdk.jpackage.test.mock.CommandMockSpec; +import jdk.jpackage.test.mock.ScriptSpec; +import jdk.jpackage.test.stdmock.JPackageMockUtils; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class LinuxDebPackagerTest { + + /** + * Exercise {@link LinuxDebPackager#buildPackage()}. + */ + @ParameterizedTest + @MethodSource + void test_buildPackage(TestSpec testSpec, @TempDir Path workDir) { + testSpec.run(workDir); + } + + record TestSpec(ScriptSpec scriptSpec, Optional> expectedErrorType) { + + TestSpec { + Objects.requireNonNull(scriptSpec); + Objects.requireNonNull(expectedErrorType); + } + + TestSpec(ScriptSpec scriptSpec) { + this(scriptSpec, Optional.empty()); + } + + TestSpec(ScriptSpec scriptSpec, Class expectedErrorType) { + this(scriptSpec, Optional.of(expectedErrorType)); + } + + void run(Path workDir) { + + var script = scriptSpec.create(); + + ExecutorFactory executorFactory = JPackageMockUtils.buildJPackage() + .script(script).listener(System.out::println).createExecutorFactory(); + + var objectFactory = ObjectFactory.build() + .executorFactory(executorFactory) + .retryExecutorFactory(new RetryExecutorFactory() { + @Override + public RetryExecutor retryExecutor(Class exceptionType) { + return RetryExecutorFactory.DEFAULT.retryExecutor(exceptionType).setSleepFunction(_ -> { + // Don't "sleep" to make the test run faster. + }); + } + }) + .create(); + + Globals.main(() -> { + Globals.instance().objectFactory(objectFactory); + + expectedErrorType.ifPresentOrElse(v -> { + var ex = assertThrows(Exception.class, () -> { + runPackagingMock(workDir); + }); + + var cause = ExceptionBox.unbox(ex); + + assertEquals(v, cause.getClass()); + }, () -> { + assertDoesNotThrow(() -> { + runPackagingMock(workDir); + }); + }); + + return 0; + }); + + assertEquals(List.of(), script.incompleteMocks()); + } + } + + private static Collection test_buildPackage() { + + Collection testCases = new ArrayList<>(); + + testCases.add(new TestSpec( + ScriptSpec.build() + .build(new CommandMockSpec("fakeroot", CommandActionSpecs.build().exit().create())) + .detailedDescription().add() + .create())); + + testCases.add(new TestSpec( + ScriptSpec.build() + .build(new CommandMockSpec("fakeroot", CommandActionSpecs.build().exit(1).create())) + .detailedDescription().add() + .create(), + UnexpectedExitCodeException.class)); + + testCases.add(new TestSpec( + ScriptSpec.build() + .build(new CommandMockSpec("fakeroot", CommandActionSpecs.build() + .stderr("semop(1): encountered an error: Invalid argument") + .exit(1).create())) + .repeat(4).detailedDescription().add() + .create(), + UnexpectedResultException.class)); + + testCases.add(new TestSpec( + ScriptSpec.build() + .build(new CommandMockSpec("fakeroot", CommandActionSpecs.build() + .stderr("semop(1): encountered an error: Invalid argument") + .exit(1).create())) + .repeat(3).detailedDescription().add() + .build(new CommandMockSpec("fakeroot", CommandActionSpecs.build().exit().create())) + .detailedDescription().add() + .create())); + + return testCases; + } + + private static LinuxDebSystemEnvironment dummySysEnv() { + + var linuxSysEnv = new LinuxSystemEnvironment.Stub(false, LINUX_DEB, new LinuxPackageArch("acme"), _ -> { + throw new AssertionError(); + }); + var debMixin = new LinuxDebSystemEnvironmentMixin.Stub(Path.of("dpkg"), Path.of("dpkg-deb"), Path.of("fakeroot")); + + return LinuxSystemEnvironment.mixin( + LinuxDebSystemEnvironment.class, + Result.ofValue(linuxSysEnv), + () -> Result.ofValue(debMixin)).orElseThrow(); + } + + private static void runPackagingMock(Path workDir) { + + var app = new ApplicationBuilder() + .appImageLayout(RuntimeLayout.DEFAULT) + .name("foo").create(); + + var sysEnv = dummySysEnv(); + + var pkg = new LinuxDebPackageBuilder( + new LinuxPackageBuilder(new PackageBuilder(app, LINUX_DEB)) + .arch(sysEnv.packageArch()) + ).create(); + + var buildEnv = new BuildEnvBuilder(workDir.resolve("build-root")).appImageDirFor(pkg).create(); + + var packager = new LinuxDebPackager(buildEnv, pkg, workDir, dummySysEnv()); + + var pipelineBuilder = LinuxPackagingPipeline.build(Optional.of(pkg)); + packager.accept(pipelineBuilder); + + // Disable actions of tasks we don't care about. + pipelineBuilder.configuredTasks().filter(taskBuilder -> { + return (taskBuilder.task() != PackageTaskID.CREATE_PACKAGE_FILE); + }).forEach(taskBuilder -> { + taskBuilder.noaction().add(); + }); + + pipelineBuilder.create().execute(buildEnv, pkg, workDir); + } +} diff --git a/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxPackageBuilderTest.java b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxPackageBuilderTest.java new file mode 100644 index 000000000000..2a760bff2715 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/linux/jdk.jpackage/jdk/jpackage/internal/LinuxPackageBuilderTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; +import jdk.jpackage.internal.model.Application; +import jdk.jpackage.internal.model.ApplicationLayout; +import jdk.jpackage.internal.model.ConfigException; +import jdk.jpackage.internal.model.StandardPackageType; +import jdk.jpackage.internal.util.CommandOutputControl.Result; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; + +class LinuxPackageBuilderTest { + + @ParameterizedTest + @EnumSource(ValidationResult.class) + void test_menuGroupNameValidation(ValidationResult validationResult, @TempDir Path workDir) { + + var counter = new AtomicInteger(); + + var builder = dummy().menuGroupName("bar").probeMenuGroupNameFile(workDir.resolve("probe.desktop")).desktopEntryFileValidator(path -> { + assertEquals(workDir.resolve("probe.desktop"), path); + assertTrue(Files.isRegularFile(path)); + + counter.incrementAndGet(); + + return switch (validationResult) { + case SUCCESS -> Result.build().exitCode(0).create(); + case EXIT_1 -> Result.build().exitCode(1).create(); + case EXIT_2 -> Result.build().exitCode(2).create(); + case UNAVAILABLE -> Result.build().create(); + }; + }); + + switch (validationResult) { + case SUCCESS, UNAVAILABLE -> assertDoesNotThrow(builder::create); + case EXIT_1, EXIT_2 -> { + var ex = assertThrowsExactly(ConfigException.class, builder::create); + + assertEquals(I18N.format("error.parameter-invalid-value", "bar", "--linux-menu-group"), ex.getMessage()); + assertEquals(I18N.format("error.invalid-desktop-category.advice"), ex.getAdvice()); + + assertEquals(null, ex.getCause()); + } + } + + assertTrue(Files.isRegularFile(workDir.resolve("probe.desktop"))); + assertEquals(1, counter.get()); + } + + @Test + void test_menuGroupNameValidation_with_probe_file_is_directory(@TempDir Path workDir) throws IOException { + + Files.createDirectory(workDir.resolve("probe.desktop")); + + var builder = dummy().menuGroupName("bar").probeMenuGroupNameFile(workDir.resolve("probe.desktop")).desktopEntryFileValidator(_ -> { + throw new AssertionError(); + }); + + assertThrowsExactly(UncheckedIOException.class, builder::create); + + assertTrue(Files.isDirectory(workDir.resolve("probe.desktop"))); + } + + @ParameterizedTest + @MethodSource + void test_menuGroupNameValidation_skip( + boolean setMenuGroupName, + boolean setProbeMenuGroupNameFile, + boolean setDesktopEntryFileValidator, + @TempDir Path workDir) throws IOException { + + Files.createDirectory(workDir.resolve("probe.desktop")); + + var builder = dummy(); + + if (setMenuGroupName) { + builder.menuGroupName("bar"); + } + + if (setProbeMenuGroupNameFile) { + builder.probeMenuGroupNameFile(workDir.resolve("probe.desktop")); + } + + if (setDesktopEntryFileValidator) { + builder.desktopEntryFileValidator(_ -> { + throw new AssertionError(); + }); + } + + assertDoesNotThrow(builder::create); + + assertTrue(Files.isDirectory(workDir.resolve("probe.desktop"))); + } + + static Collection test_menuGroupNameValidation_skip() { + + var testCases = new ArrayList(); + + for (var setMenuGroupName : List.of(true, false)) { + for (var setProbeMenuGroupNameFile : List.of(true, false)) { + for (var setDesktopEntryFileValidator : List.of(true, false)) { + if (Stream.of(setMenuGroupName, setProbeMenuGroupNameFile, setDesktopEntryFileValidator).allMatch(Boolean.TRUE::equals)) { + continue; + } + + testCases.add(Arguments.of(setMenuGroupName, setProbeMenuGroupNameFile, setDesktopEntryFileValidator)); + } + } + } + + return testCases; + } + + enum ValidationResult { + SUCCESS, + EXIT_1, + EXIT_2, + UNAVAILABLE, + ; + } + + private static LinuxPackageBuilder dummy() { + var app = new Application.Stub( + "foo", + "Foo App", + null, + null, + null, + List.of(), + List.of(), + List.of(), + ApplicationLayout.build().setAll("").create(), + Optional.empty(), + List.of(), + Map.of()); + + return new LinuxPackageBuilder(new PackageBuilder(app, StandardPackageType.LINUX_DEB)).arch(new LinuxPackageArch("acme")); + } +} diff --git a/test/jdk/tools/jpackage/junit/linux/junit.java b/test/jdk/tools/jpackage/junit/linux/junit.java index ba06cb30db77..8ff41471b311 100644 --- a/test/jdk/tools/jpackage/junit/linux/junit.java +++ b/test/jdk/tools/jpackage/junit/linux/junit.java @@ -62,3 +62,40 @@ * jdk/jpackage/internal/LinuxPackageArchTest.java * @run junit jdk.jpackage/jdk.jpackage.internal.LinuxPackageArchTest */ + +/* @test + * @summary Test LinuxPackageBuilder + * @requires (os.family == "linux") + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/LinuxPackageBuilderTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.LinuxPackageBuilderTest + */ + +/* @test + * @summary Test DesktopEntry + * @requires (os.family == "linux") + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/DesktopEntryTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.DesktopEntryTest + */ + +/* @test + * @summary Test DesktopEntryFileValidator + * @requires (os.family == "linux") + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.mock.* + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/DesktopEntryFileValidatorTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.DesktopEntryFileValidatorTest + */ + +/* @test + * @summary Test LinuxDebPackager + * @requires (os.family == "linux") + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.mock.* + * @build jdk.jpackage.test.stdmock.* + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/LinuxDebPackagerTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.LinuxDebPackagerTest + */ diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java index 85b15d77052d..30ee8a41255f 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java @@ -230,6 +230,7 @@ private Application createApplication() { null, List.of(), List.of(), + List.of(), null, Optional.empty(), new ApplicationLaunchers( diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java index 1db439469f31..23469a46088d 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java @@ -223,6 +223,7 @@ void testCreateRuntimeInstaller(boolean transformLayout, @TempDir Path workDir) .runtimeDirectory("runtime") .appModsDirectory("lib") .contentDirectory("lib") + .resourcesDirectory("lib") .desktopIntegrationDirectory("lib") .create(); } else { @@ -618,6 +619,7 @@ private static Application createApp(AppImageLayout appImageLayout, Optional pathOptionsValid() { + return Stream.of( + Arguments.of(StandardOption.APP_CONTENT, ","), + Arguments.of(StandardOption.APP_RESOURCES, File.pathSeparator) + ); + } + + @ParameterizedTest + @CsvSource({ + "app-content,COMMA", + "app-resources,PATH_SEPARATOR", + }) + public void test_AppContent_valid( + @ConvertWith(OptionValueConverter.class) OptionValue>> option, + Delimiter delimiter, @TempDir Path workDir) throws IOException { - var spec = StandardOption.APP_CONTENT.getSpec(); + var spec = option.getSpec(); var contentDir = workDir.resolve("a"); var emptyDir = contentDir.resolve("b/empty-dir"); @@ -228,10 +244,10 @@ public void test_APP_CONTENT_valid(@TempDir Path workDir) throws IOException { Object convertedValue = spec.convert( spec.name(), - StringToken.of(Stream.of(contentDir, file).map(Path::toString).collect(joining(","))) + StringToken.of(Stream.of(contentDir, file).map(Path::toString).collect(joining(delimiter.value))) ).orElseThrow(); - var paths = StandardOption.APP_CONTENT.getFrom(Options.of(Map.of(StandardOption.APP_CONTENT, convertedValue))); + var paths = option.getFrom(Options.of(Map.of(option, convertedValue))); var sortedPathList = paths.stream().flatMap(Collection::stream).map(RootedPath::branch).sorted().toList(); var expectedPathList = Stream.of( @@ -245,9 +261,27 @@ public void test_APP_CONTENT_valid(@TempDir Path workDir) throws IOException { assertEquals(expectedPathList, sortedPathList); } - @Test - public void test_APP_CONTENT_invalid(@TempDir Path workDir) throws IOException { - var spec = StandardOption.APP_CONTENT.getSpec(); + enum Delimiter { + COMMA(","), + PATH_SEPARATOR(File.pathSeparator), + ; + + Delimiter(String value) { + this.value = Objects.requireNonNull(value); + } + + private final String value; + } + + @ParameterizedTest + @CsvSource({ + "app-content", + "app-resources", + }) + public void test_AppContent_invalid( + @ConvertWith(OptionValueConverter.class) OptionValue option, + @TempDir Path workDir) throws IOException { + var spec = option.getSpec(); var token = StringToken.of(workDir.resolve("nonexistent").toString()); var result = spec.convert(spec.name(), token); @@ -951,6 +985,30 @@ private static Set filterByType(Collection ops, Class< ); } + static final class OptionValueConverter extends SimpleArgumentConverter { + + @Override + protected Object convert(Object source, Class targetType) { + if (!OptionValue.class.isAssignableFrom(targetType)) { + throw new IllegalArgumentException(); + } + + if (source == null) { + return null; + } + + if (source instanceof String optionName) { + return Utils.getOptionsWithSpecs(StandardOption.class).filter(op -> { + return op.getOption().spec().names().contains(OptionName.of(optionName)); + }).findFirst().orElseThrow(() -> { + throw new IllegalArgumentException("Failed to find standard option with the name=[" + optionName + "]"); + }); + } else { + throw new IllegalArgumentException(); + } + } + } + private static final Path GOLDEN_JPACKAGE_OPTIONS_MD = TKit.TEST_SRC_ROOT.resolve( "junit/share/jdk.jpackage/jdk/jpackage/internal/cli/jpackage-options.md"); diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-linux.txt b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-linux.txt index 8cb5b0c17cf8..1068fa962b83 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-linux.txt +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-linux.txt @@ -129,6 +129,14 @@ Options for creating the application image: --app-content [,...] A comma separated list of paths to files and/or directories to add to the application payload. + --app-content is processed after --app-resources, independent + of command-line order. + This option can be used more than once. + --app-resources [:...] + A colon-separated list of paths to files and/or directories + to add to the application's "lib" directory. + If a file from --app-resources conflicts with one from + --app-content, the file from --app-content is used. This option can be used more than once. --input -i Path of the input directory that contains the files to be packaged diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-macos.txt b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-macos.txt index 607012c16b47..91e0e773c8ef 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-macos.txt +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-macos.txt @@ -135,12 +135,20 @@ Options for creating the application image: --app-content [,...] A comma separated list of paths to files and/or directories to add to the application payload. + --app-content is processed after --app-resources, independent + of command-line order. This option can be used more than once. Note: The value should be a directory with the "Resources" subdirectory (or any other directory that is valid in the "Contents" directory of the application bundle). Otherwise, jpackage may produce invalid application bundle which may fail code signing and/or notarization. + --app-resources [:...] + A colon-separated list of paths to files and/or directories + to add to the application's "Contents/Resources" directory. + If a file from --app-resources conflicts with one from + --app-content, the file from --app-content is used. + This option can be used more than once. --input -i Path of the input directory that contains the files to be packaged (absolute path or relative to the current directory) diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-windows.txt b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-windows.txt index 89c235ac3a35..2b3096964723 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-windows.txt +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/help-windows.txt @@ -129,6 +129,14 @@ Options for creating the application image: --app-content [,...] A comma separated list of paths to files and/or directories to add to the application payload. + --app-content is processed after --app-resources, independent + of command-line order. + This option can be used more than once. + --app-resources [;...] + A semicolon-separated list of paths to files and/or directories + to add to the application image root directory. + If a file from --app-resources conflicts with one from + --app-content, the file from --app-content is used. This option can be used more than once. --input -i Path of the input directory that contains the files to be packaged diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/jpackage-options.md b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/jpackage-options.md index 59ae0d176c1e..2fac870b4895 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/jpackage-options.md +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/jpackage-options.md @@ -5,6 +5,7 @@ | --add-modules | bundle | | | | CONCATENATE | | --app-content | bundle | | | | CONCATENATE | | --app-image | mac-sign, native-bundle | | x | | USE_LAST | +| --app-resources | bundle | | | | CONCATENATE | | --app-version | bundle | x | x | | USE_LAST | | --arguments | bundle | | | x | CONCATENATE | | --copyright | bundle | x | x | | USE_LAST | diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/ApplicationLayoutTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/ApplicationLayoutTest.java index 063b11ec5895..ce4ebd1ab130 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/ApplicationLayoutTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/ApplicationLayoutTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,7 @@ public static ApplicationLayout createLayout() { .runtimeDirectory("runtime") .appModsDirectory("mods") .contentDirectory("content") + .resourcesDirectory("resources") .desktopIntegrationDirectory("lib/apps") .create(); } diff --git a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java index 9915dfd64dce..778026885483 100644 --- a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java +++ b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java @@ -78,10 +78,13 @@ public static void testHardcodedProperties() throws IOException { "Maintainer: APPLICATION_MAINTAINER", "Priority: optional", archProp.format(), - "Provides: dont-install-me", "Description: APPLICATION_DESCRIPTION", "Installed-Size: APPLICATION_INSTALLED_SIZE", - "Depends: PACKAGE_DEFAULT_DEPENDENCIES" + "Depends: PACKAGE_DEFAULT_DEPENDENCIES", + // The value of the last field must not be an empty string. + // Otherwise newer versions of dpkg-deb fails with + // "end of file before value of field 'Depends' (missing final newline)" error + "Provides: dont-install-me" )); cmd.excludeStandardAsserts(StandardAssert.LINUX_PACKAGE_ARCH); diff --git a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java index 2591d1d393a4..870d8c2cbe17 100644 --- a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java +++ b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ public static void testAdditionaltLaunchers() { */ @Test public static void testDesktopFileFromResourceDir() throws IOException { - final String expectedVersionString = "Version=12345678"; + final String expectedTryExecDesktopEntry = "TryExec=notify-send"; final Path tempDir = TKit.createTempDirectory("resources"); @@ -169,13 +169,13 @@ public static void testDesktopFileFromResourceDir() throws IOException { "Comment=APPLICATION_DESCRIPTION", "Icon=APPLICATION_ICON", "Categories=DEPLOY_BUNDLE_CATEGORY", - expectedVersionString + expectedTryExecDesktopEntry )); }) .addInstallVerifier(cmd -> { Path desktopFile = LinuxHelper.getDesktopFile(cmd); TKit.assertFileExists(desktopFile); - TKit.assertTextStream(expectedVersionString) + TKit.assertTextStream(expectedTryExecDesktopEntry) .label(String.format("[%s] file", desktopFile)) .predicate(String::equals) .apply(Files.readAllLines(desktopFile)); diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index 66b7aaa421cd..063322e045e6 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -28,6 +28,7 @@ import static jdk.internal.util.OperatingSystem.WINDOWS; import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; +import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; @@ -53,6 +54,7 @@ import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.ApplicationLayout; import jdk.jpackage.test.CannedFormattedString; import jdk.jpackage.test.ConfigurationTarget; import jdk.jpackage.test.FailedCommandErrorValidator; @@ -66,17 +68,17 @@ /** - * Tests generation of packages with additional content in app image. + * Tests generation of packages with additional content or resources in app image. */ /* * @test - * @summary jpackage with --app-content option + * @summary jpackage with --app-content or --app-resources option * @library /test/jdk/tools/jpackage/helpers * @key jpackagePlatformPackage * @build jdk.jpackage.test.* * @build AppContentTest - * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main * --jpt-run=AppContentTest */ public class AppContentTest { @@ -176,8 +178,14 @@ List expectedWarnings() { private Path appContent; } + private static Collection withOptions(Stream specs) { + return specs.flatMap(builder -> Stream.of(AppFilesOption.values()) + .map(option -> new Object[] { builder.create(option) })) + .toList(); + } + public static Collection test() { - return Stream.of( + var tests = Stream.of( build().add(TEST_JAVA).add(TEST_DUKE), build().add(TEST_JAVA).add(TEST_BAD), build().startGroup().add(TEST_JAVA).add(TEST_DUKE).endGroup().add(TEST_DIR), @@ -193,39 +201,100 @@ public static Collection test() { build().add(createTextFileContent("a/b/c/d", "Foo")).add(createTextFileContent("a", "Bar")), // Same name: one is a file, another is a directory. build().add(createTextFileContent("a", "Bar")).add(createTextFileContent("a/b/c/d", "Foo")) - ).map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); + ); + + return withOptions(tests); } public static Collection testAppImage() { - return Stream.of( + var tests = Stream.of( build().add(NonExistentPath.create("*output-app-image*", JPackageCommand::outputBundle)) - ).map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); + ); + + return withOptions(tests); } public static Collection testSymlink() { - return Stream.of( + var tests = Stream.of( build().add(TEST_JAVA) .add(new SymlinkContentFactory("Links", "duke-link", "duke-target")) .add(new SymlinkContentFactory("", "a/b/foo-link", "c/bar-target")) - ).map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); + ); + + return withOptions(tests); + } + + private enum AppFilesOption { + CONTENT("--app-content", ",", ApplicationLayout::contentDirectory, TKit.isOSX()), + RESOURCES("--app-resources", File.pathSeparator, + ApplicationLayout::resourcesDirectory, false); + + AppFilesOption(String optionName, String delimiter, + Function outputRoot, + boolean wrapInResourcesOnMac) { + this.optionName = optionName; + this.delimiter = delimiter; + this.outputRoot = outputRoot; + this.wrapInResourcesOnMac = wrapInResourcesOnMac; + } + + Path optionPath(Path path) { + if (wrapInResourcesOnMac() + && Optional.ofNullable(path.getParent()) + .map(Path::getFileName) + .map(RESOURCES_DIR::equals) + .orElse(false)) { + return path.getParent(); + } + return path; + } + + Path outputRoot(JPackageCommand cmd) { + var root = outputRoot.apply(cmd.appLayout()); + return wrapInResourcesOnMac + ? root.resolve(RESOURCES_DIR) + : root; + } + + String optionName() { + return optionName; + } + + boolean wrapInResourcesOnMac() { + return wrapInResourcesOnMac; + } + + private final String optionName; + private final String delimiter; + private final Function outputRoot; + // On OSX `--app-content` paths will be copied into the "Contents" folder + // of the output app image. + // "codesign" imposes restrictions on the directory structure of "Contents" folder. + // In particular, random files should be placed in "Contents/Resources" folder + // otherwise "codesign" will fail to sign. + // Need to prepare arguments for `--app-content` accordingly. + private final boolean wrapInResourcesOnMac; } - public record TestSpec(List> contentFactories) { + private record TestSpec(AppFilesOption option, + List> contentFactories) { public TestSpec { + Objects.requireNonNull(option); contentFactories.stream().flatMap(List::stream).forEach(Objects::requireNonNull); + if (contentFactories.isEmpty()) { + throw new IllegalArgumentException(); + } } @Override public String toString() { - return contentFactories.stream().map(group -> { + var sb = new StringBuilder(); + + sb.append(option).append(" ").append(contentFactories.stream().map(group -> { return group.stream().map(ContentFactory::toString).collect(joining(",")); - }).collect(joining("; ")); + }).collect(joining("; "))); + + return sb.toString(); } void test(ConfigurationTarget target) { @@ -242,26 +311,17 @@ void test(ConfigurationTarget target) { .addInitializer(cmd -> { contentFactories.stream().map(group -> { return group.stream().map(contentFactory -> { - return contentFactory.create(cmd); + return contentFactory.create(cmd, option.wrapInResourcesOnMac()); }).toList(); }).forEach(allContent::add); }).addInitializer(cmd -> { allContent.stream().map(group -> { - return Stream.of("--app-content", group.stream() + return Stream.of(option.optionName, group.stream() .map(Content::paths) .flatMap(List::stream) - .map(appContentArg -> { - if (COPY_IN_RESOURCES && Optional.ofNullable(appContentArg.getParent()) - .map(Path::getFileName) - .map(RESOURCES_DIR::equals) - .orElse(false)) { - return appContentArg.getParent(); - } else { - return appContentArg; - } - }) + .map(path -> option.optionPath(path)) .map(Path::toString) - .collect(joining(","))); + .collect(joining(option.delimiter))); }).flatMap(x -> x).forEachOrdered(cmd::addArgument); }); @@ -278,7 +338,7 @@ void test(ConfigurationTarget target) { return; } - var appContentRoot = getAppContentRoot(cmd); + var appContentRoot = option.outputRoot(cmd); Set disabledVerifiers = new HashSet<>(); @@ -329,8 +389,8 @@ void test(ConfigurationTarget target) { } static final class Builder { - TestSpec create() { - return new TestSpec(groups); + TestSpec create(AppFilesOption option) { + return new TestSpec(option, groups); } final class GroupBuilder { @@ -386,17 +446,8 @@ private static TestSpec.Builder build() { return new TestSpec.Builder(); } - private static Path getAppContentRoot(JPackageCommand cmd) { - final Path contentDir = cmd.appLayout().contentDirectory(); - if (COPY_IN_RESOURCES) { - return contentDir.resolve(RESOURCES_DIR); - } else { - return contentDir; - } - } - - private static Path createAppContentRoot() { - if (COPY_IN_RESOURCES) { + private static Path createAppContentRoot(boolean srcRootMustBeResourcesDir) { + if (srcRootMustBeResourcesDir) { return TKit.createTempDirectory("app-content").resolve(RESOURCES_DIR); } else { return TKit.createTempDirectory("app-content"); @@ -415,7 +466,7 @@ private static boolean isDirectoryEmpty(Path path) throws IOException { @FunctionalInterface private interface ContentFactory { - Content create(JPackageCommand cmd); + Content create(JPackageCommand cmd, boolean srcRootMustBeResourcesDir); } private interface Content { @@ -556,7 +607,7 @@ private NonExistentPath(String label, Function makePath) } @Override - public Content create(JPackageCommand cmd) { + public Content create(JPackageCommand cmd, boolean srcRootMustBeResourcesDir) { var nonexistent = makePath.apply(cmd); if (Files.exists(nonexistent)) { throw new IllegalStateException(); @@ -669,8 +720,8 @@ private record SymlinkContentFactory(Path basedir, Path symlink, Path symlinked) } @Override - public Content create(JPackageCommand cmd) { - final var appContentRoot = createAppContentRoot(); + public Content create(JPackageCommand cmd, boolean srcRootMustBeResourcesDir) { + final var appContentRoot = createAppContentRoot(srcRootMustBeResourcesDir); final var symlinkPath = appContentRoot.resolve(symlinkPath()); final var symlinkedPath = appContentRoot.resolve(symlinkedPath()); @@ -686,7 +737,7 @@ public Content create(JPackageCommand cmd) { } List contentPaths; - if (COPY_IN_RESOURCES) { + if (srcRootMustBeResourcesDir) { contentPaths = List.of(appContentRoot); } else if (basedir.equals(Path.of(""))) { contentPaths = Stream.of(symlinkPath(), symlinkedPath()).map(path -> { @@ -743,17 +794,17 @@ private static final class FileContentFactory implements ContentFactory { } @Override - public Content create(JPackageCommand cmd) { + public Content create(JPackageCommand cmd, boolean srcRootMustBeResourcesDir) { Path srcPath = factory.get(); if (!srcPath.endsWith(pathInAppContentRoot)) { throw new IllegalArgumentException(); } Path dstPath; - if (!COPY_IN_RESOURCES) { + if (!srcRootMustBeResourcesDir) { dstPath = srcPath; } else { - var contentDir = createAppContentRoot(); + var contentDir = createAppContentRoot(srcRootMustBeResourcesDir); dstPath = contentDir.resolve(pathInAppContentRoot); try { FileUtils.copyRecursive(srcPath, dstPath); @@ -778,13 +829,5 @@ public String toString() { private static final ContentFactory TEST_DIR = createDirTreeContent("apps"); private static final ContentFactory TEST_BAD = NonExistentPath.create("non-existent"); - // On OSX `--app-content` paths will be copied into the "Contents" folder - // of the output app image. - // "codesign" imposes restrictions on the directory structure of "Contents" folder. - // In particular, random files should be placed in "Contents/Resources" folder - // otherwise "codesign" will fail to sign. - // Need to prepare arguments for `--app-content` accordingly. - private static final boolean COPY_IN_RESOURCES = TKit.isOSX(); - private static final Path RESOURCES_DIR = Path.of("Resources"); } diff --git a/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java b/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java index 75c0ddfc16f1..309291f73166 100644 --- a/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java +++ b/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,33 +21,37 @@ * questions. */ -import static java.util.stream.Collectors.toMap; - import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.TreeMap; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; +import jdk.jpackage.internal.util.Slot; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.AppImageFile; import jdk.jpackage.test.ApplicationLayout; +import jdk.jpackage.test.ConfigurationTarget; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.RunnablePackageTest.Action; import jdk.jpackage.test.TKit; /* * @test * @summary test order in which jpackage fills app image * @library /test/jdk/tools/jpackage/helpers + * @key jpackagePlatformPackage * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror AppImageFillOrderTest.java * @run main/othervm/timeout=1440 -Xmx512m @@ -63,6 +67,7 @@ * Custom content comes from: *

    *
  • input directory (--input) + *
  • app resources (--app-resources) *
  • app content (--app-content) *
      */ @@ -70,8 +75,14 @@ public class AppImageFillOrderTest { @Test @ParameterSupplier - public void test(AppImageOverlay overlays[]) { - test(createJPackage().setFakeRuntime(), overlays); + public void test(AppImageOverlay overlay) { + test(initJPackage().andThen(JPackageCommand::setFakeRuntime), false, overlay); + } + + @Test + @ParameterSupplier("test") + public void testAppImage(AppImageOverlay overlay) { + test(initJPackage().andThen(JPackageCommand::setFakeRuntime), true, overlay); } /** @@ -79,27 +90,31 @@ public void test(AppImageOverlay overlays[]) { * @param jlink */ @Test - @Parameter("true") - @Parameter("false") - public void testRuntime(boolean jlink) { - var cmd = createJPackage(); - if (jlink) { - cmd.ignoreDefaultRuntime(true); - } else { - // Configure fake runtime and create it. - cmd.setFakeRuntime().executePrerequisiteActions(); - - var runtimeDir = Path.of(cmd.getArgumentValue("--runtime-image")); - if (!runtimeDir.toAbsolutePath().normalize().startsWith(TKit.workDir().toAbsolutePath().normalize())) { - throw new IllegalStateException(String.format( - "Fake runtime [%s] created outside of the test work directory [%s]", - runtimeDir, TKit.workDir())); - } + @Parameter({"true", "true"}) + @Parameter({"true", "false"}) + @Parameter({"false", "true"}) + @Parameter({"false", "false"}) + public void testRuntime(boolean appImage, boolean jlink) { + + Consumer initializer = cmd -> { + if (jlink) { + cmd.ignoreDefaultRuntime(true); + } else { + // Configure fake runtime and create it. + cmd.setFakeRuntime().executePrerequisiteActions(); + + var runtimeDir = Path.of(cmd.getArgumentValue("--runtime-image")); + if (!runtimeDir.toAbsolutePath().normalize().startsWith(TKit.workDir().toAbsolutePath().normalize())) { + throw new IllegalStateException(String.format( + "Fake runtime [%s] created outside of the test work directory [%s]", + runtimeDir, TKit.workDir())); + } - TKit.createTextFile(runtimeDir.resolve(RUNTIME_RELEASE_FILE), List.of("Foo release")); - } + TKit.createTextFile(runtimeDir.resolve(RUNTIME_RELEASE_FILE), List.of("Foo release")); + } + }; - test(cmd, AppImageAppContentOverlay.APP_CONTENT_RUNTIME_RELEASE_FILE); + test(initJPackage().andThen(initializer), appImage, StandardAppImageOverlay.APP_CONTENT_RUNTIME_RELEASE_FILE); } /** @@ -115,7 +130,7 @@ public void testAppImageFile() throws IOException { buildOverlay(cmd, TKit.createTempDirectory("app-content"), AppImageFile.getPathInAppImage(outputBundle)) .textContent("This is not a valid XML content") - .configureCmdOptions().createOverlayFile(); + .addAppContentOption().createOverlayFile(); // Run jpackage and verify it created valid .jpackage.xml file ignoring the overlay. cmd.executeAndAssertImageCreated(); @@ -124,234 +139,376 @@ public void testAppImageFile() throws IOException { AppImageFile.load(outputBundle); } - private static void test(JPackageCommand cmd, AppImageOverlay... overlays) { - if (overlays.length == 0) { - throw new IllegalArgumentException(); - } + private static void test(Consumer initializer, boolean appImage, AppImageOverlay overlay) { + Objects.requireNonNull(overlay); - final var outputDir = Path.of(cmd.getArgumentValue("--dest")); - final var noOverlaysOutputDir = Path.of(outputDir.toString() + "-no-overlay"); - cmd.setArgumentValue("--dest", noOverlaysOutputDir); - - // Run the command without overlays with redirected output directory. - cmd.execute(); - - final Optional appContentRoot; - if (Stream.of(overlays).anyMatch(AppImageAppContentOverlay.class::isInstance)) { - appContentRoot = Optional.of(TKit.createTempDirectory("app-content")); + final ConfigurationTarget targetWithoutOverlays; + if (appImage) { + targetWithoutOverlays = new ConfigurationTarget(JPackageCommand.helloAppImage()); } else { - appContentRoot = Optional.empty(); + targetWithoutOverlays = new ConfigurationTarget(new PackageTest().configureHelloApp()); } - // Apply overlays to the command. - var fileCopies = Stream.of(overlays).map(overlay -> { - switch (overlay) { - case AppImageDefaultOverlay v -> { - return v.addOverlay(cmd); - } - case AppImageAppContentOverlay v -> { - return v.addOverlay(cmd, appContentRoot.orElseThrow()); - } + targetWithoutOverlays + .addInitializer(initializer) + .addInitializer(cmdWithoutOverlays -> { + cmdWithoutOverlays.setArgumentValue("--dest", cmdWithoutOverlays.getArgumentValue("--dest") + "-no-overlay"); + }) + .apply(JPackageCommand::execute, _ -> {}) + .addInstallVerifier(cmdWithoutOverlays -> { + final ConfigurationTarget target; + if (appImage) { + target = new ConfigurationTarget(new JPackageCommand()); + } else { + target = new ConfigurationTarget(new PackageTest().forTypes(cmdWithoutOverlays.packageType())); } - }).flatMap(Collection::stream).collect(toMap(FileCopy::out, x -> x, (a, b) -> { - return b; - }, TreeMap::new)).values().stream().toList(); - - // Collect paths in the app image that will be affected by overlays. - var noOverlayOutputPaths = fileCopies.stream().map(FileCopy::out).toList(); - - fileCopies = fileCopies.stream().map(v -> { - return new FileCopy(v.in(), outputDir.resolve(noOverlaysOutputDir.relativize(v.out()))); - }).toList(); - // Restore the original output directory for the command and execute it. - cmd.setArgumentValue("--dest", outputDir).execute(); - - for (var i = 0; i != fileCopies.size(); i++) { - var noOverlayPath = noOverlayOutputPaths.get(i); - var fc = fileCopies.get(i); - TKit.assertSameFileContent(fc.in(), fc.out()); - TKit.assertMismatchFileContent(noOverlayPath, fc.out()); - } + Slot> fileCopies = Slot.createEmpty(); + + target.addInitializer(cmd -> { + cmd.clearArguments() + .addArguments(cmdWithoutOverlays.getAllArguments()) + .setDefaultInputOutput() + .setArgumentValue("--input", cmdWithoutOverlays.inputDir()); + + // Apply overlays to the command. + fileCopies.set(overlay.addOverlay(cmd).stream() + .sorted(Comparator.comparing(FileCopy::out).thenComparing(Comparator.comparing(FileCopy::in))) + .toList()); + }) + .apply(JPackageCommand::execute, _ -> {}) + .addInstallVerifier(cmd -> { + + Function unpackRoot = c -> { + return c.isImagePackageType() ? c.outputBundle() : c.pathToUnpackedPackageFile(c.appInstallationDirectory()); + }; + + for (var fc : fileCopies.get()) { + var noOverlayPath = unpackRoot.apply(cmdWithoutOverlays).resolve(fc.out()); + var overlayPath = unpackRoot.apply(cmd).resolve(fc.out()); + TKit.assertSameFileContent(fc.in(), overlayPath); + if (Files.exists(noOverlayPath)) { + TKit.assertMismatchFileContent(noOverlayPath, overlayPath); + } + } + }).test().ifPresent(test -> { + test.run(Action.CREATE_AND_UNPACK); + }); + }).test().ifPresent(test -> { + test.run(Action.CREATE_AND_UNPACK); + }); } public static Collection test() { - return Stream.of( + + var testCases = new ArrayList(); + + Stream.of( // Overwrite main launcher .cfg file from the input dir. - List.of(AppImageDefaultOverlay.INPUT_MAIN_LAUNCHER_CFG), + StandardAppImageOverlay.INPUT_MAIN_LAUNCHER_CFG, // Overwrite main launcher .cfg file from the app content dir. - List.of(AppImageAppContentOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG), + StandardAppImageOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG, // Overwrite main launcher .cfg file from the input dir and from the app content dir. // The one from app content should win. - List.of( - AppImageDefaultOverlay.INPUT_MAIN_LAUNCHER_CFG, - AppImageAppContentOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG - ), + AppImageOverlay.group().overlays( + StandardAppImageOverlay.INPUT_MAIN_LAUNCHER_CFG, + StandardAppImageOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG + ).last().create(), // Overwrite main jar from the app content dir. - List.of(AppImageAppContentOverlay.APP_CONTENT_MAIN_JAR) - ).map(args -> { - return args.toArray(AppImageOverlay[]::new); - }).map(args -> { + StandardAppImageOverlay.APP_CONTENT_MAIN_JAR, + + // The same file is copied from the --app-resources and --app-content options. + // The one from the - app-content should win regardless of the order of the options on the command line. + AppImageOverlay.group().overlays( + StandardAppImageOverlay.APP_RESOURCES_USER_FILE, + StandardAppImageOverlay.APP_CONTENT_USER_FILE).last().create(), + AppImageOverlay.group().overlays( + StandardAppImageOverlay.APP_CONTENT_USER_FILE, + StandardAppImageOverlay.APP_RESOURCES_USER_FILE).first().create() + + ).forEach(testCases::add); + + return testCases.stream().map(args -> { return new Object[] {args}; }).toList(); } - public sealed interface AppImageOverlay { - } - + @FunctionalInterface + public interface AppImageOverlay { - private enum AppImageDefaultOverlay implements AppImageOverlay { - INPUT_MAIN_LAUNCHER_CFG(AppImageFillOrderTest::replaceMainLauncherCfgFile), - ; + Collection addOverlay(JPackageCommand cmd); - AppImageDefaultOverlay(Function func) { - Objects.requireNonNull(func); - this.func = cmd -> { - return List.of(func.apply(cmd)); + static AppImageOverlay fileOverlay(BiFunction initializer) { + Objects.requireNonNull(initializer); + return cmd -> { + return List.of(initializer.apply(cmd, TKit.createTempDirectory("content")).createOverlayFile()); }; } - Collection addOverlay(JPackageCommand cmd) { - return func.apply(cmd); + static GroupAppImageOverlay.Builder group() { + return new GroupAppImageOverlay.Builder(); } - - private final Function> func; } - private enum AppImageAppContentOverlay implements AppImageOverlay { + private enum StandardAppImageOverlay implements AppImageOverlay { + + // Replace the standard main launcher .cfg file with the custom one from the input dir. + INPUT_MAIN_LAUNCHER_CFG(cmd -> { + + final var outputFile = relativize(cmd, cmd.appLauncherCfgPath(null)); + + final var inputDir = Path.of(cmd.getArgumentValue("--input")); + + final var file = inputDir.resolve(outputFile.getFileName()); + + TKit.createTextFile(file, List.of("Hello!")); + + return List.of(new FileCopy(file, outputFile)); + }), + // Replace the standard main launcher .cfg file with the custom one from the app content. - APP_CONTENT_MAIN_LAUNCHER_CFG((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLauncherCfgPath(null)) + APP_CONTENT_MAIN_LAUNCHER_CFG(AppImageOverlay.fileOverlay((cmd, contentRoot) -> { + return buildOverlay(cmd, contentRoot, cmd.appLauncherCfgPath(null)) .textContent("!Olleh") - .configureCmdOptions().createOverlayFile(); - }), + .addAppContentOption(); + })), // Replace the jar file that jpackage will pick up from the input directory with the custom one. - APP_CONTENT_MAIN_JAR((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLayout().appDirectory().resolve(cmd.getArgumentValue("--main-jar"))) + APP_CONTENT_MAIN_JAR(AppImageOverlay.fileOverlay((cmd, contentRoot) -> { + return buildOverlay(cmd, contentRoot, cmd.appLayout().appDirectory().resolve(cmd.getArgumentValue("--main-jar"))) .textContent("Surprise!") - .configureCmdOptions().createOverlayFile(); - }), + .addAppContentOption(); + })), // Replace "release" file in the runtime directory. - APP_CONTENT_RUNTIME_RELEASE_FILE((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLayout().runtimeHomeDirectory().resolve("release")) + APP_CONTENT_RUNTIME_RELEASE_FILE(AppImageOverlay.fileOverlay((cmd, contentRoot) -> { + return buildOverlay(cmd, contentRoot, cmd.appLayout().runtimeHomeDirectory().resolve("release")) .textContent("blob") - .configureCmdOptions().createOverlayFile(); - }), + .addAppContentOption(); + })), + + // "a/b/c.txt" file in the content directory. + APP_CONTENT_USER_FILE(AppImageOverlay.fileOverlay((cmd, contentRoot) -> { + var dstDir = TKit.isOSX() ? cmd.appLayout().resourcesDirectory() : cmd.appLayout().contentDirectory(); + return buildOverlay(cmd, contentRoot, dstDir.resolve("a/b/c.txt")) + .textContent("MACOS_APP_CONTENT_USER_FILE") + .addAppContentOption(); + })), + + // "a/b/c.txt" file in the resources directory. + APP_RESOURCES_USER_FILE(AppImageOverlay.fileOverlay((cmd, contentRoot) -> { + return buildOverlay(cmd, contentRoot, cmd.appLayout().resourcesDirectory().resolve("a/b/c.txt")) + .textContent("APP_RESOURCES_USER_FILE") + .addAppResourcesOption(); + })), + ; - AppImageAppContentOverlay(BiFunction func) { - Objects.requireNonNull(func); - this.func = (cmd, appContentRoot) -> { - return List.of(func.apply(cmd, appContentRoot)); - }; + StandardAppImageOverlay(AppImageOverlay impl) { + this.impl = Objects.requireNonNull(impl); } - Collection addOverlay(JPackageCommand cmd, Path appContentRoot) { - return func.apply(cmd, appContentRoot); + @Override + public Collection addOverlay(JPackageCommand cmd) { + return impl.addOverlay(cmd); } - private final BiFunction> func; + private final AppImageOverlay impl; } - private record FileCopy(Path in, Path out) { - FileCopy { - Objects.requireNonNull(in); - Objects.requireNonNull(out); + private record GroupAppImageOverlay(List group, Selector selector) implements AppImageOverlay { + + GroupAppImageOverlay { + Objects.requireNonNull(selector); + group.forEach(Objects::requireNonNull); + if (group.size() < 2) { + throw new IllegalArgumentException(); + } } - } + enum Selector { + LAST, + FIRST, + EACH, + ; + } - private static FileCopy replaceMainLauncherCfgFile(JPackageCommand cmd) { - // Replace the standard main launcher .cfg file with the custom one from the input dir. - final var outputFile = cmd.appLauncherCfgPath(null); + @Override + public Collection addOverlay(JPackageCommand cmd) { + var fileCopies = group.stream().flatMap(overlay -> { + return overlay.addOverlay(cmd).stream(); + }).toList(); - final var inputDir = Path.of(cmd.getArgumentValue("--input")); + return switch (selector) { + case EACH -> fileCopies; + case FIRST -> List.of(fileCopies.getFirst()); + case LAST -> List.of(fileCopies.getLast()); + }; + } - final var file = inputDir.resolve(outputFile.getFileName()); + @Override + public String toString() { + if (selector == Selector.EACH) { + return String.format("%s", group); + } else { + return String.format("%s%s", selector, group); + } + } - TKit.createTextFile(file, List.of("Hello!")); + final static class Builder { - return new FileCopy(file, outputFile); - } + Builder selector(Selector v) { + selector = v; + return this; + } - private static AppContentOverlayFileBuilder buildOverlay(JPackageCommand cmd, Path appContentRoot, Path outputFile) { - return new AppContentOverlayFileBuilder(cmd, appContentRoot, outputFile); - } + Builder first() { + return selector(Selector.FIRST); + } + Builder last() { + return selector(Selector.LAST); + } - private static final class AppContentOverlayFileBuilder { + Builder overlays(Collection v) { + overlays.addAll(v); + return this; + } - AppContentOverlayFileBuilder(JPackageCommand cmd, Path appContentRoot, Path outputFile) { - if (outputFile.isAbsolute()) { - throw new IllegalArgumentException(); + Builder overlays(AppImageOverlay... v) { + return overlays(List.of(v)); } - if (!outputFile.startsWith(cmd.outputBundle())) { - throw new IllegalArgumentException(); + AppImageOverlay create() { + if (overlays.size() == 1) { + return overlays.getFirst(); + } else { + return new GroupAppImageOverlay( + List.copyOf(overlays), Optional.ofNullable(selector).orElse(Selector.EACH)); + } } + private Selector selector; + private List overlays = new ArrayList<>(); + } + } + + + private record FileCopy(Path in, Path out) { + FileCopy { + Objects.requireNonNull(in); + Objects.requireNonNull(out); + } + } + + + private static OverlayFileBuilder buildOverlay(JPackageCommand cmd, Path appContentRoot, Path outputFile) { + return new OverlayFileBuilder(cmd, appContentRoot, outputFile); + } + + + private static final class OverlayFileBuilder { + + OverlayFileBuilder(JPackageCommand cmd, Path srcRoot, Path outputFile) { this.cmd = Objects.requireNonNull(cmd); - this.outputFile = Objects.requireNonNull(outputFile); - this.appContentRoot = Objects.requireNonNull(appContentRoot); + this.outputFilePathInAppImage = relativize(cmd, outputFile); + this.srcRoot = Objects.requireNonNull(srcRoot); } FileCopy createOverlayFile() { - final var file = appContentRoot.resolve(pathInAppContentDirectory()); + if (srcFile == null) { + throw new IllegalStateException(); + } try { - Files.createDirectories(file.getParent()); + Files.createDirectories(srcFile.getParent()); } catch (IOException ex) { throw new UncheckedIOException(ex); } - fileContentInitializer.accept(file); + fileContentInitializer.accept(srcFile); - return new FileCopy(file, outputFile); + return new FileCopy(srcFile, outputFilePathInAppImage); } - AppContentOverlayFileBuilder configureCmdOptions() { - cmd.addArguments("--app-content", appContentRoot.resolve(pathInAppContentDirectory().getName(0))); + OverlayFileBuilder addAppContentOption() { + addJPackageOption("--app-content", APP_IMAGE_LAYOUT.contentDirectory()); return this; } - AppContentOverlayFileBuilder content(Consumer v) { + OverlayFileBuilder addAppResourcesOption() { + addJPackageOption("--app-resources", APP_IMAGE_LAYOUT.resourcesDirectory()); + return this; + } + + OverlayFileBuilder content(Consumer v) { fileContentInitializer = v; return this; } - AppContentOverlayFileBuilder textContent(String... lines) { + OverlayFileBuilder textContent(String... lines) { return content(path -> { TKit.createTextFile(path, List.of(lines)); }); } - private Path pathInAppContentDirectory() { - return APP_IMAGE_LAYOUT.resolveAt(cmd.outputBundle()).contentDirectory().relativize(outputFile); + private void addJPackageOption(String optionName, Path outputDirectoryInAppImage) { + Objects.requireNonNull(optionName); + + var relativeSrcFilePath = relativize(outputDirectoryInAppImage, outputFilePathInAppImage); + + cmd.addArguments(optionName, srcRoot.resolve(relativeSrcFilePath.getName(0))); + + srcFile = srcRoot.resolve(relativeSrcFilePath); } private Consumer fileContentInitializer; private final JPackageCommand cmd; - private final Path outputFile; - private final Path appContentRoot; + private final Path outputFilePathInAppImage; + private final Path srcRoot; + private Path srcFile; } - private static JPackageCommand createJPackage() { - // With short name. - var cmd = JPackageCommand.helloAppImage().setArgumentValue("--name", "Foo"); + private static Path relativize(Path base, Path path) { + if (base.isAbsolute() != path.isAbsolute()) { + throw new IllegalArgumentException(); + } + + if (base.equals(Path.of(""))) { + return path; + } - // Clean leftovers in the input dir from the previous test run if any. - TKit.deleteDirectoryContentsRecursive(cmd.inputDir()); + if (!path.startsWith(base)) { + throw new IllegalArgumentException(); + } + + return base.relativize(path); + } - return cmd; + private static Path relativize(JPackageCommand cmd, Path path) { + var base = cmd.isImagePackageType() ? cmd.outputBundle() : cmd.appInstallationDirectory(); + return relativize(base, path); + } + + private static Consumer initJPackage() { + return cmd -> { + // With short name. + cmd.setArgumentValue("--name", "Foo"); + + // Fresh input dir. + cmd.setInputToEmptyDirectory(); + }; + } + + private static JPackageCommand createJPackage() { + return JPackageCommand.helloAppImage().mutate(initJPackage()); } private static final ApplicationLayout APP_IMAGE_LAYOUT = ApplicationLayout.platformAppImage(); diff --git a/test/jdk/tools/jpackage/share/BasicTest.java b/test/jdk/tools/jpackage/share/BasicTest.java index b22ca5519ad8..fabe2f0c84aa 100644 --- a/test/jdk/tools/jpackage/share/BasicTest.java +++ b/test/jdk/tools/jpackage/share/BasicTest.java @@ -47,6 +47,7 @@ import jdk.jpackage.test.Executor; import jdk.jpackage.test.HelloApp; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.JPackageOutputValidator; import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.JavaAppDesc; @@ -448,6 +449,7 @@ public void testTemp(TestTempType type) throws IOException { if (TestTempType.TEMPDIR_NOT_EMPTY.equals(type)) { pkgTest.setExpectedExitCode(1).addInitializer(cmd -> { + cmd.enableMessageCategories(MessageCategory.ERRORS); cmd.validateErr(JPackageCommand.makeError( "error.parameter-not-empty-directory", cmd.getArgumentValue("--temp"), "--temp")); }).addBundleVerifier(cmd -> { diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index a370b755dc4e..8a5911ff21b1 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -62,6 +62,7 @@ import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageOutputValidator; import jdk.jpackage.test.JavaTool; +import jdk.jpackage.test.LinuxHelper; import jdk.jpackage.test.MacSign; import jdk.jpackage.test.MacSign.CertificateRequest; import jdk.jpackage.test.MacSign.CertificateType; @@ -167,10 +168,41 @@ enum Token { EMPTY_DIR(() -> { return TKit.createTempDirectory("empty-dir"); }), - ADD_LAUNCHER_PROPERTY_FILE, + ADD_LAUNCHER_PROPERTY_FILE(() -> { + final Path propsFile = TKit.createTempFile("add-launcher.properties"); + TKit.createPropertiesFile(propsFile, Map.of()); + return propsFile; + }), EMPTY_KEYCHAIN, KEYCHAIN_WITH_APP_IMAGE_CERT, KEYCHAIN_WITH_PKG_CERT, + RESOURCE_DIR(toFunction(cmd -> { + return TKit.createTempDirectory("resources"); + })), + FAKE_RUNTIME(toFunction(cmd -> { + return JPackageCommand.createInputRuntimeImage(JPackageCommand.RuntimeImageType.RUNTIME_TYPE_FAKE); + })), + LINUX_ADD_INVALID_DESKTOP_ENTRY_FILE_RESOURCE(toFunction(cmd -> { + var resourceDir = Path.of(cmd.getArgumentValue("--resource-dir")); + TKit.createTextFile(resourceDir.resolve(cmd.mainLauncherName() + ".desktop"), List.of( + "Version=12345" + )); + return resourceDir; + })), + LINUX_ADD_INVALID_FOO_DESKTOP_ENTRY_FILE_RESOURCE(toFunction(cmd -> { + var resourceDir = Path.of(cmd.getArgumentValue("--resource-dir")); + TKit.createTextFile(resourceDir.resolve("Foo.desktop"), List.of( + "Version=54321" + )); + return resourceDir; + })), + LINUX_ADD_INVALID_ZOO_DESKTOP_ENTRY_FILE_RESOURCE(toFunction(cmd -> { + var resourceDir = Path.of(cmd.getArgumentValue("--resource-dir")); + TKit.createTextFile(resourceDir.resolve("Zoo.desktop"), List.of( + "Version=777" + )); + return resourceDir; + })), ; private Token() { @@ -187,7 +219,8 @@ private Token(Supplier valueSupplier) { }); } - String token() { + @Override + public String toString() { return makeToken(name()); } @@ -205,7 +238,7 @@ private static String makeToken(String v) { } private final Optional> valueSupplier; - private final TokenReplace tokenReplace = new TokenReplace(token()); + private final TokenReplace tokenReplace = new TokenReplace(toString()); } record PackageTypeSpec(Optional type, boolean anyNativeType) implements CannedArgument { @@ -405,6 +438,11 @@ Builder unsupportedPlatformOption(String arg, String ... otherArgs) { return addArgs(arg).addArgs(otherArgs).error("ERR_UnsupportedOption", arg); } + Builder mutate(Consumer mutator) { + mutator.accept(this); + return this; + } + TestSpec create() { return new TestSpec( Optional.ofNullable(type), @@ -450,7 +488,7 @@ void test(Map> tokenValueSuppliers) { removeArgs.forEach(cmd::removeArgumentWithValue); cmd.addArguments(addArgs); - final var tokenValueSupplier = TokenReplace.createCachingTokenValueSupplier(Stream.of(Token.values()).collect(toMap(Token::token, token -> { + final var tokenValueSupplier = TokenReplace.createCachingTokenValueSupplier(Stream.of(Token.values()).collect(toMap(Token::toString, token -> { return () -> { return token.expand(cmd).orElseGet(() -> { final var tvs = Objects.requireNonNull(tokenValueSuppliers.get(token), () -> { @@ -468,6 +506,24 @@ void test(Map> tokenValueSuppliers) { cmd.clearArguments().addArguments(newArgs); } + var resolvedExpectedMessages = expectedMessages.stream().map(cannedMessage -> { + return new CannedFormattedString( + cannedMessage.formatter(), + cannedMessage.format(), + cannedMessage.args().stream().map(arg -> { + return switch (arg) { + case String str -> { + for (final var token : Token.values()) { + str = token.asTokenReplace().applyTo(str, tokenValueSupplier); + } + yield str; + } + case Token tkn -> tokenValueSupplier.apply(tkn.toString()); + default -> arg; + }; + }).toList()); + }).toList(); + // Disable default logic adding `--verbose` option // to jpackage command line. // It will affect jpackage error messages if the command line is malformed. @@ -477,7 +533,7 @@ void test(Map> tokenValueSuppliers) { // with jpackage arguments in this test. cmd.ignoreDefaultRuntime(true); - var validator = new JPackageOutputValidator().stderr().expectMatchingStrings(expectedMessages).match(match); + var validator = new JPackageOutputValidator().stderr().expectMatchingStrings(resolvedExpectedMessages).match(match); if (match) { new JPackageOutputValidator().stdout().validateEndOfStream().applyTo(cmd); } @@ -562,10 +618,10 @@ public static Collection basic() { testSpec().appDesc("com.other/com.other.Hello").removeArgs("--module-path") .error("ERR_MissingArgument2", "--runtime-image", "--module-path"), // no main class in module path - testSpec().noAppDesc().addArgs("--module", "java.base", "--runtime-image", Token.JAVA_HOME.token()) + testSpec().noAppDesc().addArgs("--module", "java.base", "--runtime-image", Token.JAVA_HOME.toString()) .error("ERR_NoMainClass"), // no module in module path - testSpec().noAppDesc().addArgs("--module", "com.foo.bar", "--runtime-image", Token.JAVA_HOME.token()) + testSpec().noAppDesc().addArgs("--module", "com.foo.bar", "--runtime-image", Token.JAVA_HOME.toString()) .error("error.no-module-in-path", "com.foo.bar"), // non-existing argument file testSpec().noAppDesc().notype().addArgs("@foo") @@ -606,7 +662,7 @@ String[] asArray() { private static List createRuntimeMutuallyExclusive(String arg, String... otherArgs) { return createMutuallyExclusive( - new ArgumentGroup("--runtime-image", Token.JAVA_HOME.token()), + new ArgumentGroup("--runtime-image", Token.JAVA_HOME.toString()), new ArgumentGroup(arg, otherArgs) ).map(TestSpec.Builder::noAppDesc).map(TestSpec.Builder::nativeType).map(TestSpec.Builder::create).toList(); } @@ -638,6 +694,7 @@ public static Collection invalidAppVersion() { @Test @ParameterSupplier("basic") @ParameterSupplier("testRuntimeInstallerInvalidOptions") + @ParameterSupplier("testAdditionLaunchers") @ParameterSupplier(value="testWindows", ifOS = WINDOWS) @ParameterSupplier(value="testMac", ifOS = MACOS) @ParameterSupplier(value="testLinux", ifOS = LINUX) @@ -658,7 +715,8 @@ public static Collection testRuntimeInstallerInvalidOptions() { List.of("--arguments", "foo"), List.of("--java-options", "-Dfoo.bar=10"), List.of("--add-launcher", "foo=foo.properties"), - List.of("--app-content", "dir")); + List.of("--app-content", "dir"), + List.of("--app-resources", "dir")); if (TKit.isWindows()) { argsStream = Stream.concat(argsStream, Stream.of(List.of("--win-console"))); @@ -666,7 +724,7 @@ public static Collection testRuntimeInstallerInvalidOptions() { return toTestArgs(argsStream.map(args -> { var builder = testSpec().noAppDesc().nativeType() - .addArgs("--runtime-image", Token.JAVA_HOME.token()) + .addArgs("--runtime-image", Token.JAVA_HOME.toString()) .addArgs(args); if (args.contains("--add-modules")) { builder.error("ERR_MutuallyExclusiveOptions", "--runtime-image", "--add-modules"); @@ -675,27 +733,11 @@ public static Collection testRuntimeInstallerInvalidOptions() { })); } - @Test - @ParameterSupplier - public static void testAdditionLaunchers(TestSpec spec) { - final Path propsFile = TKit.createTempFile("add-launcher.properties"); - TKit.createPropertiesFile(propsFile, Map.of()); - spec.mapExpectedMessages(cannedStr -> { - return cannedStr.mapArgs(arg -> { - if (arg == Token.ADD_LAUNCHER_PROPERTY_FILE) { - return propsFile; - } else { - return arg; - } - }); - }).test(Map.of(Token.ADD_LAUNCHER_PROPERTY_FILE, cmd -> propsFile)); - } - public static Collection testAdditionLaunchers() { return toTestArgs(Stream.of( - testSpec().addArgs("--add-launcher", Token.ADD_LAUNCHER_PROPERTY_FILE.token()) + testSpec().addArgs("--add-launcher", Token.ADD_LAUNCHER_PROPERTY_FILE.toString()) .error("error.parameter-add-launcher-malformed", Token.ADD_LAUNCHER_PROPERTY_FILE, "--add-launcher"), - testSpec().removeArgs("--name").addArgs("--name", "foo", "--add-launcher", "foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE.token()) + testSpec().removeArgs("--name").addArgs("--name", "foo", "--add-launcher", "foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE.toString()) .error("error.launcher-duplicate-name", "foo") )); } @@ -749,7 +791,7 @@ public static void testMacSignWithoutIdentity(TestSpec spec) { }); } - private static void testMacSignWithoutIdentityWithNewTKitState(TestSpec spec) { + private static void testMacSignWithoutIdentityWithNewTKitState(TestSpec spec) { final Token keychainToken = spec.expectedMessages().stream().flatMap(cannedStr -> { return cannedStr.args().stream().filter(Token.class::isInstance).map(Token.class::cast).filter(token -> { switch (token) { @@ -832,8 +874,8 @@ private static void testMacSignWithoutIdentityWithNewTKitState(TestSpec spec) { public static Collection testMacSignWithoutIdentity() { final List testCases = new ArrayList<>(); - final var signArgs = List.of("--mac-sign", "--mac-signing-keychain", Token.EMPTY_KEYCHAIN.token()); - final var appImageArgs = List.of("--app-image", Token.APP_IMAGE_WITH_SHORT_NAME.token()); + final var signArgs = List.of("--mac-sign", "--mac-signing-keychain", Token.EMPTY_KEYCHAIN.toString()); + final var appImageArgs = List.of("--app-image", Token.APP_IMAGE_WITH_SHORT_NAME.toString()); for (var withAppImage : List.of(true, false)) { var builder = testSpec(); @@ -868,7 +910,7 @@ public static Collection testMacSignWithoutIdentity() { public static Collection testMacPkgSignWithoutIdentity() { final List testCases = new ArrayList<>(); - final var appImageArgs = List.of("--app-image", Token.APP_IMAGE_WITH_SHORT_NAME.token()); + final var appImageArgs = List.of("--app-image", Token.APP_IMAGE_WITH_SHORT_NAME.toString()); for (var withAppImage : List.of(true, false)) { for (var existingCertType : CertificateType.values()) { @@ -886,7 +928,7 @@ public static Collection testMacPkgSignWithoutIdentity() { var builder = testSpec() .type(PackageType.MAC_PKG) - .addArgs("--mac-sign", "--mac-signing-keychain", keychain.token()) + .addArgs("--mac-sign", "--mac-signing-keychain", keychain.toString()) .error("error.cert.not.found", missingCertificateNamePrefix, keychain); if (withAppImage) { @@ -924,8 +966,8 @@ public static void testInvalidAppName(InvalidName name) { @Test @ParameterSupplier("invalidNames") public static void testInvalidAddLauncherName(InvalidName name) { - testAdditionLaunchers(testSpec() - .addArgs("--add-launcher", name + "=" + Token.ADD_LAUNCHER_PROPERTY_FILE.token()) + test(testSpec() + .addArgs("--add-launcher", name + "=" + Token.ADD_LAUNCHER_PROPERTY_FILE.toString()) .error("ERR_InvalidSLName", adjustTextStreamVerifierArg(name.value())) .match(!name.isMessingUpConsoleOutput()) .create()); @@ -1002,7 +1044,7 @@ public static Collection testMac() { testSpec().type(PackageType.MAC_DMG).invalidTypeArg("--mac-installer-sign-identity", "foo"), testSpec().invalidTypeArg("--mac-dmg-content", "foo"), testSpec().type(PackageType.MAC_PKG).invalidTypeArg("--mac-dmg-content", "foo"), - testSpec().noAppDesc().addArgs("--app-image", Token.APP_IMAGE.token()) + testSpec().noAppDesc().addArgs("--app-image", Token.APP_IMAGE.toString()) .error("error.app-image.mac-sign.required"), testSpec().type(PackageType.MAC_PKG).addArgs("--mac-package-identifier", "#1") .error("error.parameter-not-mac-bundle-identifier", "#1", "--mac-package-identifier") @@ -1011,14 +1053,12 @@ public static Collection testMac() { testSpec().nativeType().addArgs("--mac-app-store", "--jlink-options", "--bind-services") .error("ERR_MissingJLinkOptMacAppStore", "--strip-native-commands"), // Predefined app image must be a valid macOS bundle. - testSpec().noAppDesc().nativeType().addArgs("--app-image", Token.EMPTY_DIR.token()) - .error("error.parameter-not-mac-bundle", JPackageCommand.cannedArgument(cmd -> { - return Path.of(cmd.getArgumentValue("--app-image")); - }, Token.EMPTY_DIR.token()), "--app-image"), - testSpec().nativeType().noAppDesc().addArgs("--app-image", Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.token()) + testSpec().noAppDesc().nativeType().addArgs("--app-image", Token.EMPTY_DIR.toString()) + .error("error.parameter-not-mac-bundle", Token.EMPTY_DIR, "--app-image"), + testSpec().nativeType().noAppDesc().addArgs("--app-image", Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.toString()) .error("error.invalid-app-image-plist-file", JPackageCommand.cannedArgument(cmd -> { return new MacBundle(Path.of(cmd.getArgumentValue("--app-image"))).infoPlistFile(); - }, Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.token())) + }, Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.toString())) ).map(TestSpec.Builder::create).toList()); macInvalidRuntime(testCases::add); @@ -1031,7 +1071,7 @@ public static Collection testMac() { var withoutSign = testSpec() .noAppDesc() .addArgs(argGroup.asArray()) - .addArgs("--app-image", Token.APP_IMAGE.token()); + .addArgs("--app-image", Token.APP_IMAGE.toString()); var withSign = withoutSign.copy().addArgs("--mac-sign"); @@ -1099,6 +1139,82 @@ public static Collection testLinux() { .advice("error.rpm-invalid-value-for-package-name.advice") ).map(TestSpec.Builder::create).toList()); + if (LinuxHelper.isDesktopFileValidateCommandAvailable()) { + Stream.of( + testSpec().type(PackageType.LINUX_RPM).addArgs("--linux-menu-group", "%$@#!") + .error("error.parameter-invalid-value", "%$@#!", "--linux-menu-group") + .advice("error.invalid-desktop-category.advice") + ).map(TestSpec.Builder::create).forEach(testCases::add); + + Consumer desktopValidatorInitializer = builder -> { + builder.type(PackageType.LINUX_RPM) + .addArgs("--runtime-image", Token.FAKE_RUNTIME.toString()) + .addArgs("--linux-shortcut") + .removeArgs("--name").addArgs("--name", "Wake") + .addArgs("--resource-dir", Token.RESOURCE_DIR.toString()) + .addArgs("--temp", Token.EMPTY_DIR.toString()); + }; + + // Invalid desktop entry files + Stream.of( + // Invalid main desktop entry file + testSpec().mutate(desktopValidatorInitializer) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .error("error.invalid-desktop-entry-file.main-launcher", + String.format("%s/image/opt/wake/lib/wake-Wake.desktop", Token.EMPTY_DIR)) + .advice("error.invalid-desktop-entry-file.advice"), + // Valid main desktop entry file, invalid additional launcher desktop file + testSpec().mutate(desktopValidatorInitializer) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_FOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--add-launcher", "Foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE.toString()) + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Foo.desktop", Token.EMPTY_DIR), + "Foo") + .advice("error.invalid-desktop-entry-file.advice"), + // Invalid main desktop entry file, valid additional launcher desktop file and one of additional launchers + testSpec().mutate(desktopValidatorInitializer) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_ZOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--add-launcher", "Zoo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .addArgs("--add-launcher", "Foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .error("error.invalid-desktop-entry-file.main-launcher", + String.format("%s/image/opt/wake/lib/wake-Wake.desktop", Token.EMPTY_DIR)) + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Zoo.desktop", Token.EMPTY_DIR), + "Zoo") + .advice("error.invalid-desktop-entry-file.advice"), + // Main desktop entry file and all additional launcher desktop files invalid + testSpec().mutate(desktopValidatorInitializer) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_ZOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_FOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--add-launcher", "Zoo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .addArgs("--add-launcher", "Foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .error("error.invalid-desktop-entry-file.main-launcher", + String.format("%s/image/opt/wake/lib/wake-Wake.desktop", Token.EMPTY_DIR)) + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Foo.desktop", Token.EMPTY_DIR), + "Foo") + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Zoo.desktop", Token.EMPTY_DIR), + "Zoo") + .advice("error.invalid-desktop-entry-file.advice"), + // All additional launcher desktop files invalid + testSpec().mutate(desktopValidatorInitializer) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_ZOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--resource-dir", Token.LINUX_ADD_INVALID_FOO_DESKTOP_ENTRY_FILE_RESOURCE.toString()) + .addArgs("--add-launcher", "Zoo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .addArgs("--add-launcher", "Foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE) + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Foo.desktop", Token.EMPTY_DIR), + "Foo") + .error("error.invalid-desktop-entry-file.add-launcher", + String.format("%s/image/opt/wake/lib/wake-Zoo.desktop", Token.EMPTY_DIR), + "Zoo") + .advice("error.invalid-desktop-entry-file.advice") + ).map(TestSpec.Builder::create).forEach(testCases::add); + } + invalidShortcut(testCases::add, "--linux-shortcut"); return toTestArgs(testCases.stream()); @@ -1160,14 +1276,12 @@ private static void invalidShortcut(Consumer accumulator, String short private static void macInvalidRuntime(Consumer accumulator) { var runtimeWithBinDirErr = makeError( - "error.invalid-runtime-image-bin-dir", JPackageCommand.cannedArgument(cmd -> { - return Path.of(cmd.getArgumentValue("--runtime-image")); - }, Token.JAVA_HOME.token())); + "error.invalid-runtime-image-bin-dir", Token.JAVA_HOME); var runtimeWithBinDirErrAdvice = makeAdvice( "error.invalid-runtime-image-bin-dir.advice", "--mac-app-store"); Stream.of( - testSpec().nativeType().addArgs("--mac-app-store", "--runtime-image", Token.JAVA_HOME.token()) + testSpec().nativeType().addArgs("--mac-app-store", "--runtime-image", Token.JAVA_HOME.toString()) .messages(runtimeWithBinDirErr, runtimeWithBinDirErrAdvice) ).map(TestSpec.Builder::create).forEach(accumulator); @@ -1200,14 +1314,11 @@ static MissingRuntimeFileError missingLibjli(Token runtimeDir) { } TestSpec.Builder applyTo(TestSpec.Builder builder) { - return builder.addArgs("--runtime-image", runtimeDir.token()).messages(expectedErrorMsg()); + return builder.addArgs("--runtime-image", runtimeDir.toString()).messages(expectedErrorMsg()); } private CannedFormattedString expectedErrorMsg() { - return makeError( - "error.invalid-runtime-image-missing-file", JPackageCommand.cannedArgument(cmd -> { - return Path.of(cmd.getArgumentValue("--runtime-image")); - }, runtimeDir.token()), missingFile); + return makeError("error.invalid-runtime-image-missing-file", runtimeDir, missingFile); } } diff --git a/test/jdk/tools/jpackage/share/FileAssociationsTest.java b/test/jdk/tools/jpackage/share/FileAssociationsTest.java index 0af7e7a54ff3..f8d5443d77e3 100644 --- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java +++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java @@ -31,6 +31,7 @@ import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.FileAssociations; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; @@ -149,6 +150,9 @@ private static PackageTest initPackageTest() { .excludeTypes(PackageType.MAC) .configureHelloApp() .addInitializer(JPackageCommand::setFakeRuntime) + .addInitializer(cmd -> { + cmd.enableMessageCategories(MessageCategory.ERRORS); + }) .setExpectedExitCode(1); } diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java index d66a2fdebe9b..0ed92f9d1978 100644 --- a/test/jdk/tools/jpackage/share/IconTest.java +++ b/test/jdk/tools/jpackage/share/IconTest.java @@ -327,7 +327,7 @@ private void initTest(ConfigurationTarget target) { cmd.saveConsoleOutput(true); cmd.setFakeRuntime(); cmd.addArguments(extraJPackageArgs); - cmd.setEnabledMessageCategories(MessageCategory.RESOURCES).setDisabledMessageCategories(); + cmd.enableMessageCategories(MessageCategory.RESOURCES).setDisabledMessageCategories(); }); } diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java index a9fa48dc1c6c..b6422022fd96 100644 --- a/test/jdk/tools/jpackage/share/InOutPathTest.java +++ b/test/jdk/tools/jpackage/share/InOutPathTest.java @@ -73,6 +73,7 @@ public static Collection input() { }, "--dest and --temp in --input")}, })); data.addAll(additionalContentInput(packageTypeAlias, "--app-content")); + data.addAll(additionalContentInput(packageTypeAlias, "--app-resources")); } return data; diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java index 4d5c19791908..0d11865004de 100644 --- a/test/jdk/tools/jpackage/share/InstallDirTest.java +++ b/test/jdk/tools/jpackage/share/InstallDirTest.java @@ -29,6 +29,7 @@ import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; @@ -103,6 +104,7 @@ public static void testLinuxInvalid(String installDir) { .addInitializer(cmd -> { cmd.addArguments("--install-dir", installDir); cmd.validateErr(JPackageCommand.makeError("error.invalid-install-dir", installDir)); + cmd.enableMessageCategories(MessageCategory.ERRORS); }) .run(); } diff --git a/test/jdk/tools/jpackage/share/MainClassTest.java b/test/jdk/tools/jpackage/share/MainClassTest.java index ab4dfe1e1fa3..635d5e4fc6fa 100644 --- a/test/jdk/tools/jpackage/share/MainClassTest.java +++ b/test/jdk/tools/jpackage/share/MainClassTest.java @@ -22,6 +22,8 @@ */ +import static jdk.jpackage.test.JPackageCommand.cannedArgument; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -35,17 +37,15 @@ import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.stream.Stream; - import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CannedFormattedString; -import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.CfgFile; import jdk.jpackage.test.Executor; import jdk.jpackage.test.HelloApp; import jdk.jpackage.test.JPackageCommand; -import static jdk.jpackage.test.JPackageCommand.cannedArgument; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.JavaAppDesc; import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.TKit; @@ -146,6 +146,7 @@ public MainClassTest(Script script) { cmd = JPackageCommand .helloAppImage(script.appDesc) + .enableMessageCategories(MessageCategory.ERRORS) .ignoreDefaultRuntime(true); if (!script.withJLink) { cmd.addArguments("--runtime-image", Path.of(System.getProperty( diff --git a/test/jdk/tools/jpackage/share/ModularAppTest.java b/test/jdk/tools/jpackage/share/ModularAppTest.java index d28753b4746f..8be817696da8 100644 --- a/test/jdk/tools/jpackage/share/ModularAppTest.java +++ b/test/jdk/tools/jpackage/share/ModularAppTest.java @@ -45,6 +45,7 @@ import jdk.jpackage.test.Executor; import jdk.jpackage.test.HelloApp; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.JavaAppDesc; import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.PackageType; @@ -279,6 +280,7 @@ void run() { "error.no-module-in-path", theAppDesc.moduleName()); } + cmd.enableMessageCategories(MessageCategory.ERRORS); cmd.validateErr(expectedErrorMessage).execute(1); } } diff --git a/test/jdk/tools/jpackage/share/OutputErrorTest.java b/test/jdk/tools/jpackage/share/OutputErrorTest.java index 28dca22a244b..686e45fa0dec 100644 --- a/test/jdk/tools/jpackage/share/OutputErrorTest.java +++ b/test/jdk/tools/jpackage/share/OutputErrorTest.java @@ -34,6 +34,7 @@ import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.MessageCategory; import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.TKit; @@ -59,6 +60,7 @@ public void testPackage(ExistingOutputBundleType existingOutputBundleType) { new PackageTest().configureHelloApp().addInitializer(cmd -> { cmd.setFakeRuntime(); + cmd.enableMessageCategories(MessageCategory.ERRORS); cmd.setArgumentValue("--dest", TKit.createTempDirectory("output")); cmd.removeOldOutputBundle(false); cmd.validateErr(JPackageCommand.makeError( diff --git a/test/jdk/tools/launcher/ExecutionEnvironment.java b/test/jdk/tools/launcher/ExecutionEnvironment.java index dbf20fc5bb9c..793ac6896b96 100644 --- a/test/jdk/tools/launcher/ExecutionEnvironment.java +++ b/test/jdk/tools/launcher/ExecutionEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 4780570 4731671 6354700 6367077 6670965 4882974 * @summary Checks for LD_LIBRARY_PATH and execution on *nixes * @requires os.family != "windows" + * @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*") * @library /test/lib * @modules jdk.compiler * jdk.zipfs diff --git a/test/jdk/tools/launcher/Test7029048.java b/test/jdk/tools/launcher/Test7029048.java index f92867044a16..fa0c4f871b40 100644 --- a/test/jdk/tools/launcher/Test7029048.java +++ b/test/jdk/tools/launcher/Test7029048.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary Ensure that the launcher defends against user settings of the * LD_LIBRARY_PATH environment variable on Unixes * @requires os.family != "windows" & os.family != "mac" + * @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*") * @library /test/lib * @compile ExecutionEnvironment.java Test7029048.java * @run main/othervm Test7029048 diff --git a/test/langtools/tools/javac/6863465/T6863465a.out b/test/langtools/tools/javac/6863465/T6863465a.out index 1c4513f21aae..fd354cec052a 100644 --- a/test/langtools/tools/javac/6863465/T6863465a.out +++ b/test/langtools/tools/javac/6863465/T6863465a.out @@ -1,2 +1,3 @@ +T6863465a.java:13:42: compiler.err.cant.resolve.location: kindname.class, b, , , (compiler.misc.location: kindname.class, T6863465a.c, null) T6863465a.java:11:12: compiler.err.cyclic.inheritance: T6863465a.c -1 error +2 errors diff --git a/test/langtools/tools/javac/6863465/T6863465b.out b/test/langtools/tools/javac/6863465/T6863465b.out index cb16e9336128..907b200acb43 100644 --- a/test/langtools/tools/javac/6863465/T6863465b.out +++ b/test/langtools/tools/javac/6863465/T6863465b.out @@ -1,2 +1,4 @@ +T6863465b.java:13:42: compiler.err.cant.resolve.location: kindname.class, b, , , (compiler.misc.location: kindname.class, T6863465b.c, null) +T6863465b.java:11:47: compiler.err.cant.resolve.location: kindname.class, d, , , (compiler.misc.location: kindname.class, T6863465b.z, null) T6863465b.java:11:12: compiler.err.cyclic.inheritance: T6863465b.c -1 error +3 errors diff --git a/test/langtools/tools/javac/6863465/T6863465c.out b/test/langtools/tools/javac/6863465/T6863465c.out index 1dab88a1190d..b6efbbee1c75 100644 --- a/test/langtools/tools/javac/6863465/T6863465c.out +++ b/test/langtools/tools/javac/6863465/T6863465c.out @@ -1,3 +1,4 @@ +T6863465c.java:13:42: compiler.err.cant.resolve.location: kindname.class, y, , , (compiler.misc.location: kindname.class, T6863465c.z, null) T6863465c.java:13:47: compiler.err.cant.resolve.location: kindname.class, d, , , (compiler.misc.location: kindname.class, T6863465c.z, null) T6863465c.java:11:12: compiler.err.cyclic.inheritance: T6863465c.z -2 errors +3 errors diff --git a/test/langtools/tools/javac/6863465/T6863465d.out b/test/langtools/tools/javac/6863465/T6863465d.out index b30d9effa172..3d508557443c 100644 --- a/test/langtools/tools/javac/6863465/T6863465d.out +++ b/test/langtools/tools/javac/6863465/T6863465d.out @@ -1,3 +1,5 @@ +T6863465d.java:13:42: compiler.err.cant.resolve.location: kindname.class, b, , , (compiler.misc.location: kindname.class, T6863465d.c, null) T6863465d.java:13:47: compiler.err.cant.resolve.location: kindname.class, w, , , (compiler.misc.location: kindname.class, T6863465d.c, null) +T6863465d.java:11:47: compiler.err.cant.resolve.location: kindname.class, d, , , (compiler.misc.location: kindname.class, T6863465d.z, null) T6863465d.java:11:12: compiler.err.cyclic.inheritance: T6863465d.c -2 errors +4 errors diff --git a/test/langtools/tools/javac/ClassCycle/ClassCycle5.java b/test/langtools/tools/javac/ClassCycle/ClassCycle5.java new file mode 100644 index 000000000000..84ac7251d628 --- /dev/null +++ b/test/langtools/tools/javac/ClassCycle/ClassCycle5.java @@ -0,0 +1,9 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8389058 + * @summary Verify that resolving a qualified type through a self-referential + * (cyclic) supertype doesn't crash the compiler with StackOverflowError + * @compile/fail/ref=ClassCycle5.out -XDrawDiagnostics ClassCycle5.java + */ + +class ClassCycle5 extends ClassCycle5 implements ClassCycle5.NoSuchType {} diff --git a/test/langtools/tools/javac/ClassCycle/ClassCycle5.out b/test/langtools/tools/javac/ClassCycle/ClassCycle5.out new file mode 100644 index 000000000000..fb25b22e8cf9 --- /dev/null +++ b/test/langtools/tools/javac/ClassCycle/ClassCycle5.out @@ -0,0 +1,3 @@ +ClassCycle5.java:9:61: compiler.err.cant.resolve.location: kindname.class, NoSuchType, , , (compiler.misc.location: kindname.class, ClassCycle5, null) +ClassCycle5.java:9:1: compiler.err.cyclic.inheritance: ClassCycle5 +2 errors diff --git a/test/langtools/tools/javac/patterns/DominationWithPP.out b/test/langtools/tools/javac/patterns/DominationWithPP.out index 119cc003d071..9a1c17a5cdd3 100644 --- a/test/langtools/tools/javac/patterns/DominationWithPP.out +++ b/test/langtools/tools/javac/patterns/DominationWithPP.out @@ -11,4 +11,6 @@ Domination.java:193:18: compiler.err.pattern.dominated Domination.java:202:18: compiler.err.pattern.dominated Domination.java:211:18: compiler.err.pattern.dominated Domination.java:228:18: compiler.err.pattern.dominated +- compiler.note.preview.filename: Domination.java, DEFAULT +- compiler.note.preview.recompile 13 errors diff --git a/test/langtools/tools/javac/patterns/T8309054.java b/test/langtools/tools/javac/patterns/T8309054.java index 27e9cbe0c1bf..b504624b7ff7 100644 --- a/test/langtools/tools/javac/patterns/T8309054.java +++ b/test/langtools/tools/javac/patterns/T8309054.java @@ -2,7 +2,6 @@ * @test /nodynamiccopyright/ * @bug 8309054 * @summary Parsing of erroneous patterns succeeds - * @enablePreview * @compile/fail/ref=T8309054.out -XDrawDiagnostics --should-stop=at=FLOW T8309054.java */ diff --git a/test/langtools/tools/javac/patterns/T8309054.out b/test/langtools/tools/javac/patterns/T8309054.out index 4397d51ec0be..79c187a8d222 100644 --- a/test/langtools/tools/javac/patterns/T8309054.out +++ b/test/langtools/tools/javac/patterns/T8309054.out @@ -1,7 +1,7 @@ -T8309054.java:12:24: compiler.err.expected2: :, -> -T8309054.java:16:26: compiler.err.expected2: :, -> -T8309054.java:19:35: compiler.err.expected: ')' -T8309054.java:13:13: compiler.err.switch.mixing.case.types -T8309054.java:17:13: compiler.err.switch.mixing.case.types -T8309054.java:21:17: compiler.err.unexpected.type: kindname.variable, kindname.value +T8309054.java:11:24: compiler.err.expected2: :, -> +T8309054.java:15:26: compiler.err.expected2: :, -> +T8309054.java:18:35: compiler.err.expected: ')' +T8309054.java:12:13: compiler.err.switch.mixing.case.types +T8309054.java:16:13: compiler.err.switch.mixing.case.types +T8309054.java:20:17: compiler.err.unexpected.type: kindname.variable, kindname.value 6 errors \ No newline at end of file diff --git a/test/langtools/tools/javac/patterns/T8314578.java b/test/langtools/tools/javac/patterns/T8314578.java index 28acaec3482a..11eeb310f9d2 100644 --- a/test/langtools/tools/javac/patterns/T8314578.java +++ b/test/langtools/tools/javac/patterns/T8314578.java @@ -1,7 +1,6 @@ /** * @test /nodynamiccopyright/ * @bug 8314578 - * @enablePreview * @summary Parsing of erroneous patterns succeeds * @compile/fail/ref=T8314578.out -XDrawDiagnostics T8314578.java */ diff --git a/test/langtools/tools/javac/patterns/T8314578.out b/test/langtools/tools/javac/patterns/T8314578.out index 1f09c496f57c..de1b3e7d38eb 100644 --- a/test/langtools/tools/javac/patterns/T8314578.out +++ b/test/langtools/tools/javac/patterns/T8314578.out @@ -1,4 +1,4 @@ -T8314578.java:14:18: compiler.err.flows.through.from.pattern -T8314578.java:15:18: compiler.err.flows.through.to.pattern -T8314578.java:27:18: compiler.err.flows.through.to.pattern +T8314578.java:13:18: compiler.err.flows.through.from.pattern +T8314578.java:14:18: compiler.err.flows.through.to.pattern +T8314578.java:26:18: compiler.err.flows.through.to.pattern 3 errors \ No newline at end of file diff --git a/test/langtools/tools/javac/patterns/T8332463b.out b/test/langtools/tools/javac/patterns/T8332463b.out index f912242a6c65..b5fcc5c2e4d1 100644 --- a/test/langtools/tools/javac/patterns/T8332463b.out +++ b/test/langtools/tools/javac/patterns/T8332463b.out @@ -1,2 +1,4 @@ T8332463b.java:36:18: compiler.err.pattern.dominated +- compiler.note.preview.filename: T8332463b.java, DEFAULT +- compiler.note.preview.recompile 1 error diff --git a/test/langtools/tools/javac/preview/PreviewJRTImage.java b/test/langtools/tools/javac/preview/PreviewJRTImage.java index 4e97a7688a99..fae29d0434d5 100644 --- a/test/langtools/tools/javac/preview/PreviewJRTImage.java +++ b/test/langtools/tools/javac/preview/PreviewJRTImage.java @@ -111,6 +111,8 @@ void test() { "Test.java:1:16: compiler.warn.sun.proprietary: sun.misc.Unsafe", "Test.java:5:9: compiler.err.type.found.req: java.lang.Boolean, (compiler.misc.type.req.identity)", "Test.java:7:9: compiler.warn.sun.proprietary: sun.misc.Unsafe", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", "1 error", "2 warnings" ); diff --git a/test/langtools/tools/javac/valhalla/value-objects/LoadableDescriptorsAttrTest2.java b/test/langtools/tools/javac/valhalla/value-objects/LoadableDescriptorsAttrTest2.java index e16c064b0695..8908e4ee88e5 100644 --- a/test/langtools/tools/javac/valhalla/value-objects/LoadableDescriptorsAttrTest2.java +++ b/test/langtools/tools/javac/valhalla/value-objects/LoadableDescriptorsAttrTest2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,9 +41,11 @@ import java.lang.classfile.ClassFile; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import com.sun.tools.javac.util.Assert; +import toolbox.Task.OutputKind; import toolbox.TestRunner; import toolbox.ToolBox; @@ -81,24 +83,53 @@ class Ident { Path classes = base.resolve("classes"); tb.createDirectories(classes); - new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature())) + List log; + List expected; + + expected = List.of( + "Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val", + "Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)", + "2 warnings" + ); + + log = new toolbox.JavacTask(tb) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(findJavaFiles(src)) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); + Path classFilePath = classes.resolve("Ident.class"); var classFile = ClassFile.of().parse(classFilePath); Assert.check(classFile.minorVersion() == 65535); Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent()); + expected = List.of( + "- compiler.warn.preview.feature.use.classfile: Val.class, 28", + "Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val", + "2 warnings" + ); + // now with the value class in the classpath - new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString()) + log = new toolbox.JavacTask(tb) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), + "-cp", classes.toString(), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(src.resolve("Ident.java")) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); classFilePath = classes.resolve("Ident.class"); classFile = ClassFile.of().parse(classFilePath); @@ -121,24 +152,53 @@ void m(Val val) {} Path classes = base.resolve("classes"); tb.createDirectories(classes); - new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature())) + List log; + List expected; + + expected = List.of( + "Ident.java:2:12: compiler.warn.declared.using.preview: kindname.class, Val", + "Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)", + "2 warnings" + ); + + log = new toolbox.JavacTask(tb) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(findJavaFiles(src)) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); + Path classFilePath = classes.resolve("Ident.class"); var classFile = ClassFile.of().parse(classFilePath); Assert.check(classFile.minorVersion() == 65535); Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent()); + expected = List.of( + "- compiler.warn.preview.feature.use.classfile: Val.class, 28", + "Ident.java:2:12: compiler.warn.declared.using.preview: kindname.class, Val", + "2 warnings" + ); + // now with the value class in the classpath - new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString()) + log = new toolbox.JavacTask(tb) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), + "-cp", classes.toString(), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(src.resolve("Ident.java")) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); classFilePath = classes.resolve("Ident.class"); classFile = ClassFile.of().parse(classFilePath); @@ -164,25 +224,52 @@ Val m() { Path classes = base.resolve("classes"); tb.createDirectories(classes); - new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature())) + List log; + List expected; + + expected = List.of( + "Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val", + "Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)", + "2 warnings" + ); + + log = new toolbox.JavacTask(tb) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(findJavaFiles(src)) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); + Path classFilePath = classes.resolve("Ident.class"); var classFile = ClassFile.of().parse(classFilePath); Assert.check(classFile.minorVersion() == 65535); Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent()); + expected = List.of( + "Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val", + "Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)", + "2 warnings" + ); // now with the value class in the classpath new toolbox.JavacTask(tb) - .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString()) + .options("--enable-preview", + "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString(), + "-XDrawDiagnostics", + "-Xlint:preview") .outdir(classes) .files(src.resolve("Ident.java")) .run() - .writeAll(); + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + tb.checkEqual(log, expected); classFilePath = classes.resolve("Ident.class"); classFile = ClassFile.of().parse(classFilePath); diff --git a/test/lib/jdk/test/lib/apps/LingeredApp.java b/test/lib/jdk/test/lib/apps/LingeredApp.java index f8ebc844bcb5..4e53018bf95f 100644 --- a/test/lib/jdk/test/lib/apps/LingeredApp.java +++ b/test/lib/jdk/test/lib/apps/LingeredApp.java @@ -331,6 +331,11 @@ private List runAppPrepare(String[] vmArguments) { String classpath = System.getProperty("test.class.path"); cmd.add((classpath == null) ? "." : classpath); } + // Forward test.thread.factory to child process for virtual thread testing + String testThreadFactory = System.getProperty("test.thread.factory"); + if (testThreadFactory != null) { + cmd.add("-Dtest.thread.factory=" + testThreadFactory); + } return cmd; } @@ -609,8 +614,25 @@ protected static boolean isReady() { */ @SuppressWarnings("restricted") public static void main(String args[]) { - boolean forceCrash = false; + // Checks the property directly so the app keeps working with a minimal classpath. + if ("Virtual".equals(System.getProperty("test.thread.factory"))) { + Thread t = Thread.ofVirtual().start(() -> mainLoop(args)); + try { + t.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } else { + mainLoop(args); + } + } + /** + * Runs the app on the current thread regardless of the test thread factory. + */ + @SuppressWarnings("restricted") + public static void mainLoop(String[] args) { + boolean forceCrash = false; if (args.length == 0) { System.err.println("Lock file name is not specified"); System.exit(7); diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 7aec78ee6013..88acdc10d548 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -222,6 +222,11 @@ public String printMethods(String classNamePattern, String methodPattern return printMethods0(classNamePattern, methodPattern, flags); } + public native int getMarkWordOffset(); + public native long getInlineTypePattern(); + public native long getNullFreeArrayBitInPlace(); + public native long getFlatArrayBitInPlace(); + // JVMTI private native void addToBootstrapClassLoaderSearch0(String segment); public void addToBootstrapClassLoaderSearch(String segment){ diff --git a/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java b/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java index d5da132e5f14..5770fb8a7aac 100644 --- a/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java +++ b/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,12 @@ @BenchmarkMode(Mode.AverageTime) @Fork(jvmArgs = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 3) public class PKCS12KeyStores { + @Param({"false", "true"}) + private boolean pbmac1; + + private String macAlgorithm(String legacyAlgorithm) { + return pbmac1 ? "PBEWithHmacSHA256" : legacyAlgorithm; + } private static final char[] PASS = "changeit".toCharArray(); @@ -151,14 +157,14 @@ public KeyStore instrong2048() throws Exception { public byte[] outweak2048() throws Exception { return out("PBEWithSHA1AndRC2_40", "2048", "PBEWithSHA1AndDESede", "2048", - "HmacPBESHA1", "2048"); + macAlgorithm("HmacPBESHA1"), "2048"); } @Benchmark public byte[] outweak50000_Old() throws Exception { return out("PBEWithSHA1AndRC2_40", "50000", "PBEWithSHA1AndDESede", "50000", - "HmacPBESHA1", "100000"); + macAlgorithm("HmacPBESHA1"), "100000"); // Attention: 100000 is old default Mac ic } @@ -166,7 +172,7 @@ public byte[] outweak50000_Old() throws Exception { public byte[] outstrong50000() throws Exception { return out("PBEWithHmacSHA256AndAES_256", "50000", "PBEWithHmacSHA256AndAES_256", "50000", - "HmacPBESHA256", "100000"); + macAlgorithm("HmacPBESHA256"), "100000"); // Attention: 100000 is old default Mac ic } @@ -174,13 +180,13 @@ public byte[] outstrong50000() throws Exception { public byte[] outstrong10000_New() throws Exception { return out("PBEWithHmacSHA256AndAES_256", "10000", "PBEWithHmacSHA256AndAES_256", "10000", - "HmacPBESHA256", "10000"); + macAlgorithm("HmacPBESHA256"), "10000"); } @Benchmark public byte[] outstrong2048() throws Exception { return out("PBEWithHmacSHA256AndAES_256", "2048", "PBEWithHmacSHA256AndAES_256", "2048", - "HmacPBESHA256", "2048"); + macAlgorithm("HmacPBESHA256"), "2048"); } } diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/PolynomialP256Bench.java b/test/micro/org/openjdk/bench/javax/crypto/full/PolynomialP256Bench.java index 34a6bd761ff9..8d2adb7244f4 100644 --- a/test/micro/org/openjdk/bench/javax/crypto/full/PolynomialP256Bench.java +++ b/test/micro/org/openjdk/bench/javax/crypto/full/PolynomialP256Bench.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,8 @@ import sun.security.util.math.MutableIntegerModuloP; import sun.security.util.math.ImmutableIntegerModuloP; -@Fork(jvmArgs = {"-XX:+AlwaysPreTouch", +@Fork(jvmArgs = {"-XX:+AlwaysPreTouch", "-XX:+UnlockDiagnosticVMOptions", +"-XX:CompileCommand=dontinline,sun.security.util.math.intpoly.IntegerPolynomial$MutableElement::conditionalSet", "--add-exports", "java.base/sun.security.util.math.intpoly=ALL-UNNAMED", "--add-exports", "java.base/sun.security.util.math=ALL-UNNAMED"}, value = 1) @Warmup(iterations = 3, time = 3) @@ -53,9 +54,12 @@ public class PolynomialP256Bench { final IntegerPolynomialP256 residueField = IntegerPolynomialP256.ONE; final BigInteger refx = new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16); - final ImmutableIntegerModuloP x = residueField.getElement(refx); - final ImmutableIntegerModuloP X = montField.getElement(refx); - final ImmutableIntegerModuloP one = montField.get1(); + final ImmutableIntegerModuloP xResidue = residueField.getElement(refx); + final ImmutableIntegerModuloP xMontgomery = montField.getElement(refx); + final ImmutableIntegerModuloP oneResidue = residueField.get1(); + final ImmutableIntegerModuloP oneMontgomery = montField.get1(); + final int ITERATIONS = 10_000; + boolean run = false; @Param({"true", "false"}) private boolean isMontBench; @@ -63,43 +67,54 @@ public class PolynomialP256Bench { @Benchmark public MutableIntegerModuloP benchMultiply() { MutableIntegerModuloP test; + if (isMontBench) { - test = X.mutable(); + test = xMontgomery.mutable(); } else { - test = x.mutable(); + test = xResidue.mutable(); } - - for (int i = 0; i< 10000; i++) { + for (int i = 0; i < ITERATIONS; i++) { test = test.setProduct(test); } + return test; } @Benchmark public MutableIntegerModuloP benchSquare() { MutableIntegerModuloP test; + if (isMontBench) { - test = X.mutable(); + test = xMontgomery.mutable(); } else { - test = x.mutable(); + test = xResidue.mutable(); } - - for (int i = 0; i< 10000; i++) { + for (int i = 0; i < ITERATIONS; i++) { test = test.setSquare(); } + return test; } @Benchmark public MutableIntegerModuloP benchAssign() { - MutableIntegerModuloP test1 = X.mutable(); - MutableIntegerModuloP test2 = one.mutable(); - for (int i = 0; i< 10000; i++) { + MutableIntegerModuloP test1; + MutableIntegerModuloP test2; + + if (isMontBench) { + test1 = xMontgomery.mutable(); + test2 = oneMontgomery.mutable(); + } else { + test1 = xResidue.mutable(); + test2 = oneResidue.mutable(); + } + for (int i = 0; i < ITERATIONS; i++) { test1.conditionalSet(test2, 0); test1.conditionalSet(test2, 1); test2.conditionalSet(test1, 0); test2.conditionalSet(test1, 1); } + return test2; } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java index b70588906af9..9a3d6319df94 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java @@ -98,6 +98,218 @@ public void longMaskAndNot() { } } + @Benchmark + public void byteMaskNot() { + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm = VectorMask.fromArray(B_SPECIES, ma, i); + vm.not().intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskNot() { + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm = VectorMask.fromArray(S_SPECIES, ma, i); + vm.not().intoArray(mc, i); + } + } + + @Benchmark + public void intMaskNot() { + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm = VectorMask.fromArray(I_SPECIES, ma, i); + vm.not().intoArray(mc, i); + } + } + + @Benchmark + public void longMaskNot() { + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm = VectorMask.fromArray(L_SPECIES, ma, i); + vm.not().intoArray(mc, i); + } + } + + @Benchmark + public void byteMaskNand() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.and(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskNand() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.and(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void intMaskNand() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.and(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void longMaskNand() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.and(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void byteMaskNor() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.or(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskNor() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.or(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void intMaskNor() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.or(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void longMaskNor() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.or(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void byteMaskXnor() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.xor(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskXnor() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.xor(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void intMaskXnor() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.xor(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void longMaskXnor() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.xor(vm2).not().intoArray(mc, i); + } + } + + @Benchmark + public void byteMaskEq() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.eq(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskEq() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.eq(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void intMaskEq() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.eq(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void longMaskEq() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.eq(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void byteMaskOrNot() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.or(vm2.not()).intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskOrNot() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.or(vm2.not()).intoArray(mc, i); + } + } + + @Benchmark + public void intMaskOrNot() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.or(vm2.not()).intoArray(mc, i); + } + } + + @Benchmark + public void longMaskOrNot() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.or(vm2.not()).intoArray(mc, i); + } + } + @Benchmark public int highMaskRegisterPressureWithNots() { int res = 0; @@ -114,4 +326,4 @@ public int highMaskRegisterPressureWithNots() { } return res; } -} \ No newline at end of file +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/EncodeDecodeBench.java b/test/micro/org/openjdk/bench/vm/compiler/EncodeDecodeBench.java new file mode 100644 index 000000000000..b20eba06aab7 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/EncodeDecodeBench.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * test encoding and decoding of heap oop + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3) +public class EncodeDecodeBench { + + static final class IntHolder { + public int value; + + IntHolder(int value) { + this.value = value; + } + } + + @Param("100000") + private int arraySize; + + @Param("0.1") + private double nullRatio; + + private IntHolder[] arrayA; + private IntHolder[] arrayB; + + @Setup + public void setup() { + arrayA = new IntHolder[arraySize]; + arrayB = new IntHolder[arraySize]; + Random random = new Random(0); + for (int i = 0; i < arraySize; i++) { + arrayA[i] = (random.nextDouble() < nullRatio) ? null : new IntHolder(i); + } + } + + @Benchmark + public IntHolder[] testEncode() { + IntHolder[] a = arrayA; + IntHolder[] b = arrayB; + for (int i = 0; i < a.length; i++) { + IntHolder holder = a[i]; + if (holder != null) { + holder.value += 1; + } + b[i] = holder; + } + return b; + } + + @Benchmark + public int testDecode() { + // Count the nulls so that the decode-and-compare branch is actually + // taken for some elements; see count() below. + return count(arrayA, null); + } + + // DONT_INLINE keeps 'v' unknown to C2 compiler. So C2 can not do + // null constatnt optimization. + // + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private int count(IntHolder[] a, IntHolder v) { + int cnt = 0; + for (int i = 0; i < a.length; i++) { + IntHolder holder = a[i]; + if (holder == v) { + cnt++; + } + } + return cnt; + } +}