diff --git a/.github/actions/get-msys2/action.yml b/.github/actions/get-msys2/action.yml index 3e6c3417a31..f6de676a327 100644 --- a/.github/actions/get-msys2/action.yml +++ b/.github/actions/get-msys2/action.yml @@ -34,11 +34,11 @@ runs: with: install: 'autoconf tar unzip zip make' path-type: minimal - location: msys2 + location: ${{ runner.tool_cache }}/msys2 # We can't run bash until this is completed, so stick with pwsh - name: 'Set MSYS2 path' run: | # Prepend msys2/msys64/usr/bin to the PATH - echo "$env:GITHUB_WORKSPACE/msys2/msys64/usr/bin" >> $env:GITHUB_PATH + echo "$env:RUNNER_TOOL_CACHE/msys2/msys64/usr/bin" >> $env:GITHUB_PATH shell: pwsh diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index e57db3b63e8..8973219f0ab 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -125,6 +125,7 @@ jobs: # We need a minimal PATH on Windows # Set PATH to "", so just GITHUB_PATH is included PATH: '' + shell: env /usr/bin/bash --login -eo pipefail {0} - name: 'Build' id: build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ab22d1c7f45..cf6d69afefd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,7 +35,7 @@ on: platforms: description: 'Platform(s) to execute on (comma separated, e.g. "linux-x64, macos, aarch64")' required: true - default: 'linux-x64, linux-x86, linux-x64-variants, linux-cross-compile, macos-x64, macos-aarch64, windows-x64, windows-aarch64' + default: 'linux-x64, linux-x86, linux-x64-variants, linux-cross-compile, macos-x64, macos-aarch64, windows-x64, windows-aarch64, docs' configure-arguments: description: 'Additional configure arguments' required: false @@ -65,6 +65,7 @@ jobs: macos-aarch64: ${{ steps.include.outputs.macos-aarch64 }} windows-x64: ${{ steps.include.outputs.windows-x64 }} windows-aarch64: ${{ steps.include.outputs.windows-aarch64 }} + docs: ${{ steps.include.outputs.docs }} steps: # This function must be inlined in main.yml, or we'd be forced to checkout the repo @@ -77,19 +78,17 @@ jobs: # 'false' otherwise. # arg $1: platform name or names to look for function check_platform() { - if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then - # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything - echo 'false' - return - fi - if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then input='${{ github.event.inputs.platforms }}' elif [[ $GITHUB_EVENT_NAME == push ]]; then - input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' - else - echo 'Internal error in GHA' - exit 1 + if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then + # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything + >&2 echo 'JDK_SUBMIT_FILTER is set and not a "submit/" branch' + echo 'false' + return + else + input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' + fi fi normalized_input="$(echo ,$input, | tr -d ' ')" @@ -118,6 +117,7 @@ jobs: echo "macos-aarch64=$(check_platform macos-aarch64 macos aarch64)" >> $GITHUB_OUTPUT echo "windows-x64=$(check_platform windows-x64 windows x64)" >> $GITHUB_OUTPUT echo "windows-aarch64=$(check_platform windows-aarch64 windows aarch64)" >> $GITHUB_OUTPUT + echo "docs=$(check_platform docs)" >> $GITHUB_OUTPUT ### ### Build jobs @@ -278,6 +278,23 @@ jobs: make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.select.outputs.windows-aarch64 == 'true' + build-docs: + name: docs + needs: select + uses: ./.github/workflows/build-linux.yml + with: + platform: linux-x64 + debug-levels: '[ "debug" ]' + make-target: 'docs-jdk-bundles' + # Make sure we never try to make full docs, since that would require a + # build JDK, and we do not need the additional testing of the graphs. + extra-conf-options: '--disable-full-docs' + gcc-major-version: '10' + apt-gcc-version: '10.4.0-4ubuntu1~22.04' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + if: needs.select.outputs.docs == 'true' + ### ### Test jobs ### diff --git a/.jcheck/conf b/.jcheck/conf index 6f2de4d3805..8993c274fe0 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk jbs=JDK -version=20 +version=21 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index 6aa6047ede9..777d69b0a2e 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -72,6 +72,7 @@

HotSpot Coding Style

  • Expression SFINAE
  • enum
  • +
  • alignas
  • thread_local
  • nullptr
  • <atomic>
  • @@ -598,7 +599,7 @@

    C++ Standard Library

    std::numeric_limits.
  • #include <type_traits>.
  • #include <cstddef> to use -std::nullptr_t.
  • +std::nullptr_t and std::max_align_t.

    TODO: Rather than directly #including (permitted) Standard Library headers, use a convention of #including wrapper headers (in some @@ -670,6 +671,53 @@

    enum

    constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants.

    +

    alignas

    +

    Alignment-specifiers (alignas n2341) +are permitted, with restrictions.

    +

    Alignment-specifiers are permitted when the requested +alignment is a fundamental alignment (not greater than +alignof(std::max_align_t) C++14 +3.11/2).

    +

    Alignment-specifiers with an extended alignment +(greater than alignof(std::max_align_t) C++14 +3.11/3) may only be used to align variables with static or automatic +storage duration (C++14 +3.7.1, 3.7.3). As a consequence, over-aligned types are +forbidden; this may change if HotSpot updates to using C++17 or later +(p0035r4).

    +

    Large extended alignments should be avoided, particularly +for stack allocated objects. What is a large value may depend on the +platform and configuration. There may also be hard limits for some +platforms.

    +

    An alignment-specifier must always be applied to a +definition (C++14 +10.6.2/6). (C++ allows an alignment-specifier to optionally +also be applied to a declaration, so long as the definition has +equivalent alignment. There isn't any known benefit from duplicating the +alignment in a non-definition declaration, so such duplication should be +avoided in HotSpot code.)

    +

    Enumerations are forbidden from having alignment-specifiers. +Aligned enumerations were originally permitted but insufficiently +specified, and were later (C++20) removed (CWG 2354). +Permitting such usage in HotSpot now would just cause problems in the +future.

    +

    Alignment-specifiers are forbidden in typedef +and alias-declarations. This may work or may have worked in +some versions of some compilers, but was later (C++14) explicitly +disallowed (CWG +1437).

    +

    The HotSpot macro ATTRIBUTE_ALIGNED provides similar +capabilities for platforms that define it. This macro predates the use +by HotSpot of C++ versions providing alignas. New code +should use alignas.

    thread_local

    Avoid use of thread_local (n2659); diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index eeb9d21e74c..555453498d3 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -573,7 +573,7 @@ There are a few exceptions to this rule. * `#include ` to use placement `new`, `std::nothrow`, and `std::nothrow_t`. * `#include ` to use `std::numeric_limits`. * `#include `. -* `#include ` to use `std::nullptr_t`. +* `#include ` to use `std::nullptr_t` and `std::max_align_t`. TODO: Rather than directly \#including (permitted) Standard Library headers, use a convention of \#including wrapper headers (in some @@ -651,6 +651,51 @@ constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants. +### alignas + +_Alignment-specifiers_ (`alignas` +[n2341](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf)) +are permitted, with restrictions. + +_Alignment-specifiers_ are permitted when the requested alignment is a +_fundamental alignment_ (not greater than `alignof(std::max_align_t)` +[C++14 3.11/2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). + +_Alignment-specifiers_ with an _extended alignment_ (greater than +`alignof(std::max_align_t)` +[C++14 3.11/3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)) +may only be used to align variables with static or automatic storage duration +([C++14 3.7.1, 3.7.3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). +As a consequence, _over-aligned types_ are forbidden; this may change if +HotSpot updates to using C++17 or later +([p0035r4](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r4.html)). + +Large _extended alignments_ should be avoided, particularly for stack +allocated objects. What is a large value may depend on the platform and +configuration. There may also be hard limits for some platforms. + +An _alignment-specifier_ must always be applied to a definition +([C++14 10.6.2/6](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). +(C++ allows an _alignment-specifier_ to optionally also be applied to a +declaration, so long as the definition has equivalent alignment. There isn't +any known benefit from duplicating the alignment in a non-definition +declaration, so such duplication should be avoided in HotSpot code.) + +Enumerations are forbidden from having _alignment-specifiers_. Aligned +enumerations were originally permitted but insufficiently specified, and were +later (C++20) removed +([CWG 2354](https://cplusplus.github.io/CWG/issues/2354.html)). +Permitting such usage in HotSpot now would just cause problems in the future. + +_Alignment-specifiers_ are forbidden in `typedef` and _alias-declarations_. +This may work or may have worked in some versions of some compilers, but was +later (C++14) explicitly disallowed +([CWG 1437](https://cplusplus.github.io/CWG/issues/1437.html)). + +The HotSpot macro `ATTRIBUTE_ALIGNED` provides similar capabilities for +platforms that define it. This macro predates the use by HotSpot of C++ +versions providing `alignas`. New code should use `alignas`. + ### thread_local Avoid use of `thread_local` diff --git a/doc/testing.html b/doc/testing.html index b88eb0c5024..9962b6b3415 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -494,6 +494,9 @@

    REPEAT_COUNT

    Repeat the tests up to a set number of times, stopping at first failure. This helps to reproduce intermittent test failures. Defaults to 0.

    +

    REPORT

    +

    Use this report style when reporting test results (sent to JTReg as +-report). Defaults to files.

    Gtest keywords

    REPEAT

    The number of times to repeat the tests diff --git a/doc/testing.md b/doc/testing.md index db6c39db3cf..9535388346b 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -484,6 +484,11 @@ Repeat the tests up to a set number of times, stopping at first failure. This helps to reproduce intermittent test failures. Defaults to 0. +#### REPORT + +Use this report style when reporting test results (sent to JTReg as `-report`). +Defaults to `files`. + ### Gtest keywords #### REPEAT diff --git a/make/Docs.gmk b/make/Docs.gmk index 0cc5309813f..33d531ee4d2 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -102,6 +102,10 @@ REFERENCE_TAGS := $(JAVADOC_TAGS) JAVADOC_DISABLED_DOCLINT_WARNINGS := missing JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio +# Allow overriding on the command line +# (intentionally sharing name with the javac option) +JAVA_WARNINGS_ARE_ERRORS ?= -Werror + # The initial set of options for javadoc JAVADOC_OPTIONS := -use -keywords -notimestamp \ -encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \ @@ -333,6 +337,7 @@ define SetupApiDocsGenerationBody # Ignore the doclint warnings in certain packages $1_OPTIONS += -Xdoclint/package:$$(call CommaList, $$(addprefix -, \ $$(JAVADOC_DISABLED_DOCLINT_PACKAGES))) + $1_OPTIONS += $$(JAVA_WARNINGS_ARE_ERRORS) $1_DOC_TITLE := $$($1_LONG_NAME)
    Version $$(VERSION_SPECIFICATION) API \ Specification @@ -614,7 +619,7 @@ $(foreach n, 0 1 2, \ $(eval specs_bottom_rel_path := $(specs_bottom_rel_path)../) \ ) -SPECS_TOP := $(if $(filter true, $(IS_DRAFT)),

    $(DRAFT_TEXT)
    ) +SPECS_TOP := $(if $(filter true, $(IS_DRAFT)), ) # For all html files in $module/share/specs directories, copy and add the # copyright footer. diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 5fa0c381ebb..894e09528e0 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 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 @@ -196,11 +196,12 @@ $(eval $(call SetTestOpt,JAVA_OPTIONS,JTREG)) $(eval $(call SetTestOpt,JOBS,JTREG)) $(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG)) $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) +$(eval $(call SetTestOpt,REPORT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT REPEAT_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ + RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \ $(CUSTOM_JTREG_STRING_KEYWORDS), \ @@ -352,7 +353,7 @@ ExpandJtregPath = \ # with test id: dir/Test.java#selection -> Test.java#selection -> .java#selection -> #selection # without: dir/Test.java -> Test.java -> .java -> <> TestID = \ - $(subst .java,,$(suffix $(notdir $1))) + $(subst .sh,,$(subst .html,,$(subst .java,,$(suffix $(notdir $1))))) # The test id starting with a hash (#testid) will be stripped by all # evals in ParseJtregTestSelectionInner and will be reinserted by calling @@ -745,6 +746,7 @@ define SetupRunJtregTestBody JTREG_RUN_PROBLEM_LISTS ?= false JTREG_RETRY_COUNT ?= 0 JTREG_REPEAT_COUNT ?= 0 + JTREG_REPORT ?= files ifneq ($$(JTREG_RETRY_COUNT), 0) ifneq ($$(JTREG_REPEAT_COUNT), 0) @@ -857,6 +859,7 @@ define SetupRunJtregTestBody -dir:$$(JTREG_TOPDIR) \ -reportDir:$$($1_TEST_RESULTS_DIR) \ -workDir:$$($1_TEST_SUPPORT_DIR) \ + -report:$${JTREG_REPORT} \ $$$${JTREG_STATUS} \ $$(JTREG_OPTIONS) \ $$(JTREG_FAILURE_HANDLER_OPTIONS) \ diff --git a/make/ZipSource.gmk b/make/ZipSource.gmk index 49d13433372..341af7e9847 100644 --- a/make/ZipSource.gmk +++ b/make/ZipSource.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -31,6 +31,7 @@ include JavaCompilation.gmk include Modules.gmk SRC_ZIP_WORK_DIR := $(SUPPORT_OUTPUTDIR)/src +$(if $(filter $(TOPDIR)/%, $(SUPPORT_OUTPUTDIR)), $(eval SRC_ZIP_BASE := $(TOPDIR)), $(eval SRC_ZIP_BASE := $(SUPPORT_OUTPUTDIR))) # Hook to include the corresponding custom file, if present. $(eval $(call IncludeCustomExtension, ZipSource.gmk)) @@ -45,10 +46,10 @@ ALL_MODULES := $(FindAllModules) # again to create src.zip. $(foreach m, $(ALL_MODULES), \ $(foreach d, $(call FindModuleSrcDirs, $m), \ - $(eval $d_TARGET := $(SRC_ZIP_WORK_DIR)/$(patsubst $(TOPDIR)/%,%,$d)/$m) \ + $(eval $d_TARGET := $(SRC_ZIP_WORK_DIR)/$(patsubst $(TOPDIR)/%,%,$(patsubst $(SUPPORT_OUTPUTDIR)/%,%,$d))/$m) \ $(if $(SRC_GENERATED), , \ $(eval $$($d_TARGET): $d ; \ - $$(if $(filter $(TOPDIR)/%, $d), $$(link-file-relative), $$(link-file-absolute)) \ + $$(if $(filter $(SRC_ZIP_BASE)/%, $d), $$(link-file-relative), $$(link-file-absolute)) \ ) \ ) \ $(eval SRC_ZIP_SRCS += $$($d_TARGET)) \ diff --git a/make/autoconf/build-aux/config.guess b/make/autoconf/build-aux/config.guess index b08072b556c..daf45ae414d 100644 --- a/make/autoconf/build-aux/config.guess +++ b/make/autoconf/build-aux/config.guess @@ -29,7 +29,40 @@ # and fix the broken property, if needed. DIR=`dirname $0` -OUT=`. $DIR/autoconf-config.guess` +OUT=`. $DIR/autoconf-config.guess 2> /dev/null` + +# Handle some cases that autoconf-config.guess is not capable of +if [ "x$OUT" = x ]; then + if [ `uname -s` = Linux ]; then + # Test and fix little endian MIPS. + if [ `uname -m` = mipsel ]; then + OUT=mipsel-unknown-linux-gnu + elif [ `uname -m` = mips64el ]; then + OUT=mips64el-unknown-linux-gnu + # Test and fix little endian PowerPC64. + elif [ `uname -m` = ppc64le ]; then + OUT=powerpc64le-unknown-linux-gnu + # Test and fix LoongArch64. + elif [ `uname -m` = loongarch64 ]; then + OUT=loongarch64-unknown-linux-gnu + # Test and fix RISC-V. + elif [ `uname -m` = riscv64 ]; then + OUT=riscv64-unknown-linux-gnu + fi + # Test and fix cygwin machine arch .x86_64 + elif [[ `uname -s` = CYGWIN* ]]; then + if [ `uname -m` = ".x86_64" ]; then + OUT=x86_64-unknown-cygwin + fi + fi + + if [ "x$OUT" = x ]; then + # Run autoconf-config.guess again to get the error message. + . $DIR/autoconf-config.guess > /dev/null + else + printf "guessed by custom config.guess... " >&2 + fi +fi # Detect C library. # Use '-gnu' suffix on systems that use glibc. @@ -81,45 +114,6 @@ if test $? = 0; then OUT=powerpc$KERNEL_BITMODE`echo $OUT | sed -e 's/[^-]*//'` fi -# Test and fix little endian PowerPC64. -# TODO: should be handled by autoconf-config.guess. -if [ "x$OUT" = x ]; then - if [ `uname -m` = ppc64le ]; then - if [ `uname -s` = Linux ]; then - OUT=powerpc64le-unknown-linux-gnu - fi - fi -fi - -# Test and fix little endian MIPS. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = mipsel ]; then - OUT=mipsel-unknown-linux-gnu - elif [ `uname -m` = mips64el ]; then - OUT=mips64el-unknown-linux-gnu - fi - fi -fi - -# Test and fix LoongArch64. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = loongarch64 ]; then - OUT=loongarch64-unknown-linux-gnu - fi - fi -fi - -# Test and fix RISC-V. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = riscv64 ]; then - OUT=riscv64-unknown-linux-gnu - fi - fi -fi - # Test and fix cpu on macos-aarch64, uname -p reports arm, buildsys expects aarch64 echo $OUT | grep arm-apple-darwin > /dev/null 2> /dev/null if test $? != 0; then diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index fd3723b4683..05f2a51a7ed 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -215,6 +215,9 @@ JDKOPT_SETUP_CODE_COVERAGE # AddressSanitizer JDKOPT_SETUP_ADDRESS_SANITIZER +# UndefinedBehaviorSanitizer +JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER + ############################################################################### # # Check dependencies for external and internal libraries. diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index ebae9e8f00f..1fdd0143adf 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -532,7 +532,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], # Suggested additions: -qsrcmsg to get improved error reporting # set -qtbtable=full for a better traceback table/better stacks in hs_err when xlc16 is used TOOLCHAIN_CFLAGS_JDK="-qtbtable=full -qchars=signed -qfullpath -qsaveopt -qstackprotect" # add on both CFLAGS - TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced \ + TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced -fno-exceptions \ -qalias=noansi -qstrict -qtls=default -qnortti -qnoeh -qignerrno -qstackprotect" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then TOOLCHAIN_CFLAGS_JVM="-nologo -MD -Zc:preprocessor -Zc:strictStrings -MP" diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4 index 9b5cb4b3751..ddb2b4c8e0a 100644 --- a/make/autoconf/flags.m4 +++ b/make/autoconf/flags.m4 @@ -503,14 +503,14 @@ UTIL_DEFUN_NAMED([FLAGS_CXX_COMPILER_CHECK_ARGUMENTS], UTIL_DEFUN_NAMED([FLAGS_COMPILER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE PREFIX], [$@], [ - FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARG_ARGUMENT], + FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: ARG_ARGUMENT, IF_TRUE: [C_COMP_SUPPORTS="yes"], IF_FALSE: [C_COMP_SUPPORTS="no"], - PREFIX: [ARG_PREFIX]) - FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARG_ARGUMENT], + PREFIX: ARG_PREFIX) + FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: ARG_ARGUMENT, IF_TRUE: [CXX_COMP_SUPPORTS="yes"], IF_FALSE: [CXX_COMP_SUPPORTS="no"], - PREFIX: [ARG_PREFIX]) + PREFIX: ARG_PREFIX) AC_MSG_CHECKING([if both ARG_PREFIX[CC] and ARG_PREFIX[CXX] support "ARG_ARGUMENT"]) supports=no diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 05bff5d5001..64f1bf09010 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -445,6 +445,41 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER], AC_SUBST(ASAN_ENABLED) ]) +############################################################################### +# +# UndefinedBehaviorSanitizer +# +AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER], +[ + UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED, + DESC: [enable UndefinedBehaviorSanitizer], + CHECK_AVAILABLE: [ + AC_MSG_CHECKING([if UndefinedBehaviorSanitizer (ubsan) is available]) + if test "x$TOOLCHAIN_TYPE" = "xgcc" || + test "x$TOOLCHAIN_TYPE" = "xclang"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AVAILABLE=false + fi + ], + IF_ENABLED: [ + # GCC reports lots of likely false positives for stringop-truncation and format-overflow. + # Silence them for now. + UBSAN_CFLAGS="-fsanitize=undefined -fsanitize=float-divide-by-zero -Wno-stringop-truncation -Wno-format-overflow -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER" + UBSAN_LDFLAGS="-fsanitize=undefined -fsanitize=float-divide-by-zero" + JVM_CFLAGS="$JVM_CFLAGS $UBSAN_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $UBSAN_LDFLAGS" + CFLAGS_JDKLIB="$CFLAGS_JDKLIB $UBSAN_CFLAGS" + CFLAGS_JDKEXE="$CFLAGS_JDKEXE $UBSAN_CFLAGS" + CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $UBSAN_CFLAGS" + CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $UBSAN_CFLAGS" + LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $UBSAN_LDFLAGS" + LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $UBSAN_LDFLAGS" + ]) + AC_SUBST(UBSAN_ENABLED) +]) + ################################################################################ # # Static build support. When enabled will generate static @@ -781,7 +816,7 @@ AC_DEFUN([JDKOPT_SETUP_MACOSX_SIGNING], # Check for user provided code signing identity. UTIL_ARG_WITH(NAME: macosx-codesign-identity, TYPE: string, - DEFAULT: openjdk_codesign, CHECK_VALUE: UTIL_CHECK_STRING_NON_EMPTY, + DEFAULT: openjdk_codesign, CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY], DESC: [specify the macosx code signing identity], CHECKING_MSG: [for macosx code signing identity] ) diff --git a/make/autoconf/jdk-version.m4 b/make/autoconf/jdk-version.m4 index 41f4b1fb121..3639299105e 100644 --- a/make/autoconf/jdk-version.m4 +++ b/make/autoconf/jdk-version.m4 @@ -69,149 +69,132 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(JDK_RC_PLATFORM_NAME) AC_SUBST(HOTSPOT_VM_DISTRO) + # Note: UTIL_ARG_WITH treats empty strings as valid values when OPTIONAL is false! + + # Outer [ ] to quote m4. + [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] + # Setup username (for use in adhoc version strings etc) - AC_ARG_WITH([build-user], [AS_HELP_STRING([--with-build-user], - [build username to use in version strings])]) - if test "x$with_build_user" = xyes || test "x$with_build_user" = xno; then - AC_MSG_ERROR([--with-build-user must have a value]) - elif test "x$with_build_user" != x; then - USERNAME="$with_build_user" - else - # Outer [ ] to quote m4. - [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] - fi + UTIL_ARG_WITH(NAME: build-user, TYPE: string, + RESULT: USERNAME, + DEFAULT: $USERNAME, + DESC: [build username to use in version strings], + DEFAULT_DESC: [current username, sanitized], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY]) AC_SUBST(USERNAME) # Set the JDK RC name - AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name], - [Set JDK RC name. This is used for FileDescription and ProductName properties - of MS Windows binaries. @<:@not specified@:>@])]) - if test "x$with_jdk_rc_name" = xyes || test "x$with_jdk_rc_name" = xno; then - AC_MSG_ERROR([--with-jdk-rc-name must have a value]) - elif [ ! [[ $with_jdk_rc_name =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-jdk-rc-name contains non-printing characters: $with_jdk_rc_name]) - elif test "x$with_jdk_rc_name" != x; then - # Set JDK_RC_NAME to a custom value if '--with-jdk-rc-name' was used and is not empty. - JDK_RC_NAME="$with_jdk_rc_name" - else - # Otherwise calculate from "branding.conf" included above. - JDK_RC_NAME="$PRODUCT_NAME $JDK_RC_PLATFORM_NAME" - fi + # Otherwise calculate from "branding.conf" included above. + UTIL_ARG_WITH(NAME: jdk-rc-name, TYPE: string, + DEFAULT: $PRODUCT_NAME $JDK_RC_PLATFORM_NAME, + DESC: [Set JDK RC name. This is used for FileDescription and ProductName + properties of MS Windows binaries.], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(JDK_RC_NAME) # The vendor name, if any - AC_ARG_WITH(vendor-name, [AS_HELP_STRING([--with-vendor-name], - [Set vendor name. Among others, used to set the 'java.vendor' - and 'java.vm.vendor' system properties. @<:@not specified@:>@])]) - if test "x$with_vendor_name" = xyes || test "x$with_vendor_name" = xno; then - AC_MSG_ERROR([--with-vendor-name must have a value]) - elif [ ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-vendor-name contains non-printing characters: $with_vendor_name]) - elif test "x$with_vendor_name" != x; then - # Only set COMPANY_NAME if '--with-vendor-name' was used and is not empty. - # Otherwise we will use the value from "branding.conf" included above. - COMPANY_NAME="$with_vendor_name" - fi + # Only set COMPANY_NAME if '--with-vendor-name' was used and is not empty. + # Otherwise we will use the value from "branding.conf" included above. + UTIL_ARG_WITH(NAME: vendor-name, TYPE: string, + RESULT: COMPANY_NAME, + DEFAULT: $COMPANY_NAME, + DESC: [Set vendor name. Among others, used to set the 'java.vendor' + and 'java.vm.vendor' system properties.], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(COMPANY_NAME) # The vendor URL, if any - AC_ARG_WITH(vendor-url, [AS_HELP_STRING([--with-vendor-url], - [Set the 'java.vendor.url' system property @<:@not specified@:>@])]) - if test "x$with_vendor_url" = xyes || test "x$with_vendor_url" = xno; then - AC_MSG_ERROR([--with-vendor-url must have a value]) - elif [ ! [[ $with_vendor_url =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-vendor-url contains non-printing characters: $with_vendor_url]) - elif test "x$with_vendor_url" != x; then - # Only set VENDOR_URL if '--with-vendor-url' was used and is not empty. - # Otherwise we will use the value from "branding.conf" included above. - VENDOR_URL="$with_vendor_url" - fi + # Only set VENDOR_URL if '--with-vendor-url' was used and is not empty. + # Otherwise we will use the value from "branding.conf" included above. + UTIL_ARG_WITH(NAME: vendor-url, TYPE: string, + DEFAULT: $VENDOR_URL, + DESC: [Set the 'java.vendor.url' system property], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(VENDOR_URL) # The vendor bug URL, if any - AC_ARG_WITH(vendor-bug-url, [AS_HELP_STRING([--with-vendor-bug-url], - [Set the 'java.vendor.url.bug' system property @<:@not specified@:>@])]) - if test "x$with_vendor_bug_url" = xyes || test "x$with_vendor_bug_url" = xno; then - AC_MSG_ERROR([--with-vendor-bug-url must have a value]) - elif [ ! [[ $with_vendor_bug_url =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-vendor-bug-url contains non-printing characters: $with_vendor_bug_url]) - elif test "x$with_vendor_bug_url" != x; then - # Only set VENDOR_URL_BUG if '--with-vendor-bug-url' was used and is not empty. - # Otherwise we will use the value from "branding.conf" included above. - VENDOR_URL_BUG="$with_vendor_bug_url" - fi + # Only set VENDOR_URL_BUG if '--with-vendor-bug-url' was used and is not empty. + # Otherwise we will use the value from "branding.conf" included above. + UTIL_ARG_WITH(NAME: vendor-bug-url, TYPE: string, + RESULT: VENDOR_URL_BUG, + DEFAULT: $VENDOR_URL_BUG, + DESC: [Set the 'java.vendor.url.bug' system property], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(VENDOR_URL_BUG) # The vendor VM bug URL, if any - AC_ARG_WITH(vendor-vm-bug-url, [AS_HELP_STRING([--with-vendor-vm-bug-url], - [Sets the bug URL which will be displayed when the VM crashes @<:@not specified@:>@])]) - if test "x$with_vendor_vm_bug_url" = xyes || test "x$with_vendor_vm_bug_url" = xno; then - AC_MSG_ERROR([--with-vendor-vm-bug-url must have a value]) - elif [ ! [[ $with_vendor_vm_bug_url =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-vendor-vm-bug-url contains non-printing characters: $with_vendor_vm_bug_url]) - elif test "x$with_vendor_vm_bug_url" != x; then - # Only set VENDOR_URL_VM_BUG if '--with-vendor-vm-bug-url' was used and is not empty. - # Otherwise we will use the value from "branding.conf" included above. - VENDOR_URL_VM_BUG="$with_vendor_vm_bug_url" - fi + # Only set VENDOR_URL_VM_BUG if '--with-vendor-vm-bug-url' was used and is not empty. + # Otherwise we will use the value from "branding.conf" included above. + UTIL_ARG_WITH(NAME: vendor-vm-bug-url, TYPE: string, + RESULT: VENDOR_URL_VM_BUG, + DEFAULT: $VENDOR_URL_VM_BUG, + DESC: [Sets the bug URL which will be displayed when the VM crashes], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(VENDOR_URL_VM_BUG) # Override version from arguments # If --with-version-string is set, process it first. It is possible to # override parts with more specific flags, since these are processed later. - AC_ARG_WITH(version-string, [AS_HELP_STRING([--with-version-string], - [Set version string @<:@calculated@:>@])]) - if test "x$with_version_string" = xyes || test "x$with_version_string" = xno; then - AC_MSG_ERROR([--with-version-string must have a value]) - elif test "x$with_version_string" != x; then - # Additional [] needed to keep m4 from mangling shell constructs. - if [ [[ $with_version_string =~ ^([0-9]+)(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(-([a-zA-Z0-9]+))?(((\+)([0-9]*))?(-([-a-zA-Z0-9.]+))?)?$ ]] ]; then - VERSION_FEATURE=${BASH_REMATCH[[1]]} - VERSION_INTERIM=${BASH_REMATCH[[3]]} - VERSION_UPDATE=${BASH_REMATCH[[5]]} - VERSION_PATCH=${BASH_REMATCH[[7]]} - VERSION_EXTRA1=${BASH_REMATCH[[9]]} - VERSION_EXTRA2=${BASH_REMATCH[[11]]} - VERSION_EXTRA3=${BASH_REMATCH[[13]]} - VERSION_PRE=${BASH_REMATCH[[15]]} - version_plus_separator=${BASH_REMATCH[[18]]} - VERSION_BUILD=${BASH_REMATCH[[19]]} - VERSION_OPT=${BASH_REMATCH[[21]]} - # Unspecified numerical fields are interpreted as 0. - if test "x$VERSION_INTERIM" = x; then - VERSION_INTERIM=0 - fi - if test "x$VERSION_UPDATE" = x; then - VERSION_UPDATE=0 - fi - if test "x$VERSION_PATCH" = x; then - VERSION_PATCH=0 - fi - if test "x$VERSION_EXTRA1" = x; then - VERSION_EXTRA1=0 + UTIL_ARG_WITH(NAME: version-string, TYPE: string, + DEFAULT: [], + DESC: [Set version string], + DEFAULT_DESC: [calculated], + CHECK_VALUE: [ + if test "x$RESULT" != x; then + # Additional [] needed to keep m4 from mangling shell constructs. + if [ [[ $RESULT =~ ^([0-9]+)(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(-([a-zA-Z0-9]+))?(((\+)([0-9]*))?(-([-a-zA-Z0-9.]+))?)?$ ]] ]; then + VERSION_FEATURE=${BASH_REMATCH[[1]]} + VERSION_INTERIM=${BASH_REMATCH[[3]]} + VERSION_UPDATE=${BASH_REMATCH[[5]]} + VERSION_PATCH=${BASH_REMATCH[[7]]} + VERSION_EXTRA1=${BASH_REMATCH[[9]]} + VERSION_EXTRA2=${BASH_REMATCH[[11]]} + VERSION_EXTRA3=${BASH_REMATCH[[13]]} + VERSION_PRE=${BASH_REMATCH[[15]]} + version_plus_separator=${BASH_REMATCH[[18]]} + VERSION_BUILD=${BASH_REMATCH[[19]]} + VERSION_OPT=${BASH_REMATCH[[21]]} + # Unspecified numerical fields are interpreted as 0. + if test "x$VERSION_INTERIM" = x; then + VERSION_INTERIM=0 + fi + if test "x$VERSION_UPDATE" = x; then + VERSION_UPDATE=0 + fi + if test "x$VERSION_PATCH" = x; then + VERSION_PATCH=0 + fi + if test "x$VERSION_EXTRA1" = x; then + VERSION_EXTRA1=0 + fi + if test "x$VERSION_EXTRA2" = x; then + VERSION_EXTRA2=0 + fi + if test "x$VERSION_EXTRA3" = x; then + VERSION_EXTRA3=0 + fi + if test "x$version_plus_separator" != x \ + && test "x$VERSION_BUILD$VERSION_OPT" = x; then + AC_MSG_ERROR([Version string contains + but both 'BUILD' and 'OPT' are missing]) + fi + if test "x$VERSION_BUILD" = x0; then + AC_MSG_WARN([Version build 0 is interpreted as no build number]) + VERSION_BUILD= + fi + # Stop the version part process from setting default values. + # We still allow them to explicitly override though. + NO_DEFAULT_VERSION_PARTS=true + else + FAILURE="--with-version-string fails to parse as a valid version string: $RESULT" + fi fi - if test "x$VERSION_EXTRA2" = x; then - VERSION_EXTRA2=0 - fi - if test "x$VERSION_EXTRA3" = x; then - VERSION_EXTRA3=0 - fi - if test "x$version_plus_separator" != x \ - && test "x$VERSION_BUILD$VERSION_OPT" = x; then - AC_MSG_ERROR([Version string contains + but both 'BUILD' and 'OPT' are missing]) - fi - if test "x$VERSION_BUILD" = x0; then - AC_MSG_WARN([Version build 0 is interpreted as no build number]) - VERSION_BUILD= - fi - # Stop the version part process from setting default values. - # We still allow them to explicitly override though. - NO_DEFAULT_VERSION_PARTS=true - else - AC_MSG_ERROR([--with-version-string fails to parse as a valid version string: $with_version_string]) - fi - fi + ]) AC_ARG_WITH(version-pre, [AS_HELP_STRING([--with-version-pre], [Set the base part of the version 'PRE' field (pre-release identifier) @<:@'internal'@:>@])], @@ -290,23 +273,19 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], fi fi - AC_ARG_WITH(version-feature, [AS_HELP_STRING([--with-version-feature], - [Set version 'FEATURE' field (first number) @<:@current source value@:>@])], - [with_version_feature_present=true], [with_version_feature_present=false]) - - if test "x$with_version_feature_present" = xtrue; then - if test "x$with_version_feature" = xyes || test "x$with_version_feature" = xno; then - AC_MSG_ERROR([--with-version-feature must have a value]) - else - JDKVER_CHECK_AND_SET_NUMBER(VERSION_FEATURE, $with_version_feature) - fi - else - if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then - # Default is to get value from version-numbers.conf - VERSION_FEATURE="$DEFAULT_VERSION_FEATURE" - fi + # Default is to get value from version-numbers.conf + if test "x$NO_DEFAULT_VERSION_PARTS" = xtrue; then + DEFAULT_VERSION_FEATURE="$VERSION_FEATURE" fi + UTIL_ARG_WITH(NAME: version-feature, TYPE: string, + DEFAULT: $DEFAULT_VERSION_FEATURE, + DESC: [Set version 'FEATURE' field (first number)], + DEFAULT_DESC: [current source value], + CHECK_VALUE: [ + JDKVER_CHECK_AND_SET_NUMBER(VERSION_FEATURE, $RESULT) + ]) + AC_ARG_WITH(version-interim, [AS_HELP_STRING([--with-version-interim], [Set version 'INTERIM' field (second number) @<:@current source value@:>@])], [with_version_interim_present=true], [with_version_interim_present=false]) @@ -480,91 +459,81 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], VERSION_SHORT=$VERSION_NUMBER${VERSION_PRE:+-$VERSION_PRE} # The version date - AC_ARG_WITH(version-date, [AS_HELP_STRING([--with-version-date], - [Set version date @<:@current source value@:>@])]) - if test "x$with_version_date" = xyes || test "x$with_version_date" = xno; then - AC_MSG_ERROR([--with-version-date must have a value]) - elif test "x$with_version_date" != x; then - if [ ! [[ $with_version_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] ]; then - AC_MSG_ERROR(["$with_version_date" is not a valid version date]) - else - VERSION_DATE="$with_version_date" - fi - else - VERSION_DATE="$DEFAULT_VERSION_DATE" - fi + UTIL_ARG_WITH(NAME: version-date, TYPE: string, + DEFAULT: $DEFAULT_VERSION_DATE, + DESC: [Set version date], + DEFAULT_DESC: [current source value], + CHECK_VALUE: [ + if test "x$RESULT" = x; then + FAILURE="--with-version-date cannot be empty" + elif [ ! [[ $RESULT =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] ]; then + FAILURE="\"$RESULT\" is not a valid version date" + fi + ]) # The vendor version string, if any - AC_ARG_WITH(vendor-version-string, [AS_HELP_STRING([--with-vendor-version-string], - [Set vendor version string @<:@not specified@:>@])]) - if test "x$with_vendor_version_string" = xyes; then - AC_MSG_ERROR([--with-vendor-version-string must have a value]) - elif [ ! [[ $with_vendor_version_string =~ ^[[:graph:]]*$ ]] ]; then - AC_MSG_ERROR([--with--vendor-version-string contains non-graphical characters: $with_vendor_version_string]) - elif test "x$with_vendor_version_string" != xno; then - # Set vendor version string if --without is not passed - # Check not required if an empty value is passed, since VENDOR_VERSION_STRING - # would then be set to "" - VENDOR_VERSION_STRING="$with_vendor_version_string" + # DEFAULT is set to an empty string in the case of --with-vendor-version-string without + # any value, which would set VENDOR_VERSION_STRING_ENABLED to true and ultimately also + # cause VENDOR_VERSION_STRING to fall back to the value in DEFAULT + UTIL_ARG_WITH(NAME: vendor-version-string, TYPE: string, + DEFAULT: [], + OPTIONAL: true, + DESC: [Set vendor version string], + DEFAULT_DESC: [not specified]) + + if test "x$VENDOR_VERSION_STRING_ENABLED" = xtrue; then + if [ ! [[ $VENDOR_VERSION_STRING =~ ^[[:graph:]]*$ ]] ]; then + AC_MSG_ERROR([--with--vendor-version-string contains non-graphical characters: $VENDOR_VERSION_STRING]) + fi fi # Set the MACOSX Bundle Name base - AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base], - [Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names. - @<:@not specified@:>@])]) - if test "x$with_macosx_bundle_name_base" = xyes || test "x$with_macosx_bundle_name_base" = xno; then - AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value]) - elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base]) - elif test "x$with_macosx_bundle_name_base" != x; then - # Set MACOSX_BUNDLE_NAME_BASE to the configured value. - MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base" - fi + UTIL_ARG_WITH(NAME: macosx-bundle-name-base, TYPE: string, + DEFAULT: $MACOSX_BUNDLE_NAME_BASE, + DESC: [Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.], + DEFAULT_DESC: [from branding.conf], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(MACOSX_BUNDLE_NAME_BASE) - # Set the MACOSX Bundle ID base - AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base], - [Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs. - @<:@not specified@:>@])]) - if test "x$with_macosx_bundle_id_base" = xyes || test "x$with_macosx_bundle_id_base" = xno; then - AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value]) - elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base]) - elif test "x$with_macosx_bundle_id_base" != x; then - # Set MACOSX_BUNDLE_ID_BASE to the configured value. - MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base" - else - # If using the default value, append the VERSION_PRE if there is one - # to make it possible to tell official builds apart from developer builds - if test "x$VERSION_PRE" != x; then - MACOSX_BUNDLE_ID_BASE="$MACOSX_BUNDLE_ID_BASE-$VERSION_PRE" - fi + # If using the default value, append the VERSION_PRE if there is one + # to make it possible to tell official builds apart from developer builds + if test "x$VERSION_PRE" != x; then + MACOSX_BUNDLE_ID_BASE="$MACOSX_BUNDLE_ID_BASE-$VERSION_PRE" fi + + # Set the MACOSX Bundle ID base + UTIL_ARG_WITH(NAME: macosx-bundle-id-base, TYPE: string, + DEFAULT: $MACOSX_BUNDLE_ID_BASE, + DESC: [Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.], + DEFAULT_DESC: [based on branding.conf and VERSION_PRE], + CHECK_VALUE: [UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE]) AC_SUBST(MACOSX_BUNDLE_ID_BASE) - # Set the MACOSX CFBundleVersion field - AC_ARG_WITH(macosx-bundle-build-version, [AS_HELP_STRING([--with-macosx-bundle-build-version], - [Set the MacOSX Bundle CFBundleVersion field. This key is a machine-readable - string composed of one to three period-separated integers and should represent the - build version. Defaults to the build number.])]) - if test "x$with_macosx_bundle_build_version" = xyes || test "x$with_macosx_bundle_build_version" = xno; then - AC_MSG_ERROR([--with-macosx-bundle-build-version must have a value]) - elif [ ! [[ $with_macosx_bundle_build_version =~ ^[0-9\.]*$ ]] ]; then - AC_MSG_ERROR([--with-macosx-bundle-build-version contains non numbers and periods: $with_macosx_bundle_build_version]) - elif test "x$with_macosx_bundle_build_version" != x; then - MACOSX_BUNDLE_BUILD_VERSION="$with_macosx_bundle_build_version" + if test "x$VERSION_BUILD" != x; then + MACOSX_BUNDLE_BUILD_VERSION="$VERSION_BUILD" else - if test "x$VERSION_BUILD" != x; then - MACOSX_BUNDLE_BUILD_VERSION="$VERSION_BUILD" - else - MACOSX_BUNDLE_BUILD_VERSION=0 - fi + MACOSX_BUNDLE_BUILD_VERSION=0 + fi - # If VERSION_OPT consists of only numbers and periods, add it. - if [ [[ $VERSION_OPT =~ ^[0-9\.]+$ ]] ]; then - MACOSX_BUNDLE_BUILD_VERSION="$MACOSX_BUNDLE_BUILD_VERSION.$VERSION_OPT" - fi + # If VERSION_OPT consists of only numbers and periods, add it. + if [ [[ $VERSION_OPT =~ ^[0-9\.]+$ ]] ]; then + MACOSX_BUNDLE_BUILD_VERSION="$MACOSX_BUNDLE_BUILD_VERSION.$VERSION_OPT" fi + + # Set the MACOSX CFBundleVersion field + UTIL_ARG_WITH(NAME: macosx-bundle-build-version, TYPE: string, + DEFAULT: $MACOSX_BUNDLE_BUILD_VERSION, + DESC: [Set the MacOSX Bundle CFBundleVersion field. This key is a machine-readable + string composed of one to three period-separated integers and should represent the + build version.], + DEFAULT_DESC: [the build number], + CHECK_VALUE: [ + if test "x$RESULT" = x; then + FAILURE="--with-macosx-bundle-build-version must have a value" + elif [ ! [[ $RESULT =~ ^[0-9\.]*$ ]] ]; then + FAILURE="--with-macosx-bundle-build-version contains non numbers and periods: $RESULT" + fi + ]) AC_SUBST(MACOSX_BUNDLE_BUILD_VERSION) # We could define --with flags for these, if really needed diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 0b4b138ccd7..9d3080d2050 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -28,7 +28,7 @@ ################################################################################ # Minimum supported version -JTREG_MINIMUM_VERSION=7.1 +JTREG_MINIMUM_VERSION=7.1.1 ############################################################################### # diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 9448cb9b7e8..1daed61c983 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -455,6 +455,9 @@ ifeq ($(ASAN_ENABLED), yes) endif endif +# UndefinedBehaviorSanitizer +UBSAN_ENABLED:=@UBSAN_ENABLED@ + # Necessary additional compiler flags to compile X11 X_CFLAGS:=@X_CFLAGS@ X_LIBS:=@X_LIBS@ diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 index d2171338d00..83349aea99d 100644 --- a/make/autoconf/util.m4 +++ b/make/autoconf/util.m4 @@ -52,7 +52,7 @@ m4_include([util_paths.m4]) AC_DEFUN([UTIL_DEFUN_NAMED], [ AC_DEFUN($1, [ - m4_foreach(arg, m4_split(m4_normalize($2)), [ + m4_foreach([arg], m4_split(m4_normalize($2)), [ m4_if(m4_bregexp(arg, [^\*]), -1, [ m4_set_add(legal_named_args, arg) @@ -64,13 +64,18 @@ AC_DEFUN([UTIL_DEFUN_NAMED], ) ]) - m4_foreach([arg], [$3], [ - m4_if(m4_bregexp(arg, [: ]), -1, m4_define([arg], m4_bpatsubst(arg, [:], [: ]))) - m4_define(arg_name, m4_substr(arg, 0, m4_bregexp(arg, [: ]))) + # Delicate quoting and unquoting sequence to ensure the actual value is passed along unchanged + # For details on how this works, see https://git.openjdk.org/jdk/pull/11458#discussion_r1038173051 + # WARNING: Proceed at the risk of your own sanity, getting this to work has made me completely + # incapable of feeling love or any other positive emotion + # ~Julian + m4_foreach([arg], m4_dquote(m4_dquote_elt($3)), [ + m4_if(m4_index(arg, [: ]), -1, [m4_define([arg], m4_dquote(m4_bpatsubst(m4_dquote(arg), [:], [: ])))]) + m4_define(arg_name, m4_substr(arg, 0, m4_index(arg, [: ]))) m4_set_contains(legal_named_args, arg_name, [],[AC_MSG_ERROR([Internal error: m4_if(arg_name, , arg, arg_name) is not a valid named argument to [$1]. Valid arguments are 'm4_set_contents(defined_args, [ ]) m4_set_contents(legal_named_args, [ ])'.])]) m4_set_remove(required_named_args, arg_name) m4_set_remove(legal_named_args, arg_name) - m4_pushdef([ARG_][]arg_name, m4_bpatsubst(m4_substr(arg, m4_incr(m4_incr(m4_bregexp(arg, [: ])))), [^\s*], [])) + m4_pushdef([ARG_][]arg_name, m4_bpatsubst(m4_bpatsubst(m4_dquote(m4_dquote(arg)), arg_name[: ]), [^\s*])) m4_set_add(defined_args, arg_name) m4_undefine([arg_name]) ]) @@ -376,18 +381,18 @@ UTIL_DEFUN_NAMED([UTIL_ARG_ENABLE], m4_define(ARG_GIVEN, m4_translit(ARG_NAME, [a-z-], [A-Z_])[_GIVEN]) # If DESC is not specified, set it to a generic description. - m4_define([ARG_DESC], m4_if(ARG_DESC, , [Enable the ARG_NAME feature], m4_normalize(ARG_DESC))) + m4_define([ARG_DESC], m4_if(m4_quote(ARG_DESC), , [[Enable the ARG_NAME feature]], [m4_normalize(ARG_DESC)])) # If CHECKING_MSG is not specified, set it to a generic description. - m4_define([ARG_CHECKING_MSG], m4_if(ARG_CHECKING_MSG, , [for --enable-ARG_NAME], m4_normalize(ARG_CHECKING_MSG))) + m4_define([ARG_CHECKING_MSG], m4_if(m4_quote(ARG_CHECKING_MSG), , [[for --enable-ARG_NAME]], [m4_normalize(ARG_CHECKING_MSG)])) # If the code blocks are not given, set them to the empty statements to avoid # tripping up bash. - m4_define([ARG_CHECK_AVAILABLE], m4_if(ARG_CHECK_AVAILABLE, , :, ARG_CHECK_AVAILABLE)) - m4_define([ARG_IF_GIVEN], m4_if(ARG_IF_GIVEN, , :, ARG_IF_GIVEN)) - m4_define([ARG_IF_NOT_GIVEN], m4_if(ARG_IF_NOT_GIVEN, , :, ARG_IF_NOT_GIVEN)) - m4_define([ARG_IF_ENABLED], m4_if(ARG_IF_ENABLED, , :, ARG_IF_ENABLED)) - m4_define([ARG_IF_DISABLED], m4_if(ARG_IF_DISABLED, , :, ARG_IF_DISABLED)) + m4_if(ARG_CHECK_AVAILABLE, , [m4_define([ARG_CHECK_AVAILABLE], [:])]) + m4_if(ARG_IF_GIVEN, , [m4_define([ARG_IF_GIVEN], [:])]) + m4_if(ARG_IF_NOT_GIVEN, , [m4_define([ARG_IF_NOT_GIVEN], [:])]) + m4_if(ARG_IF_ENABLED, , [m4_define([ARG_IF_ENABLED], [:])]) + m4_if(ARG_IF_DISABLED, , [m4_define([ARG_IF_DISABLED], [:])]) ########################## # Part 2: Set up autoconf shell code @@ -650,21 +655,21 @@ UTIL_DEFUN_NAMED([UTIL_ARG_WITH], m4_define(ARG_GIVEN, m4_translit(ARG_NAME, [a-z-], [A-Z_])[_GIVEN]) # If DESC is not specified, set it to a generic description. - m4_define([ARG_DESC], m4_if(ARG_DESC, , [Give a value for the ARG_NAME feature], m4_normalize(ARG_DESC))) + m4_define([ARG_DESC], m4_if(m4_quote(ARG_DESC), , [[Give a value for the ARG_NAME feature]], [m4_normalize(ARG_DESC)])) # If CHECKING_MSG is not specified, set it to a generic description. - m4_define([ARG_CHECKING_MSG], m4_if(ARG_CHECKING_MSG, , [for --with-ARG_NAME], m4_normalize(ARG_CHECKING_MSG))) + m4_define([ARG_CHECKING_MSG], m4_if(m4_quote(ARG_CHECKING_MSG), , [[for --with-ARG_NAME]], [m4_normalize(ARG_CHECKING_MSG)])) m4_define([ARG_HAS_AUTO_BLOCK], m4_if(ARG_IF_AUTO, , false, true)) # If the code blocks are not given, set them to the empty statements to avoid # tripping up bash. - m4_define([ARG_CHECK_AVAILABLE], m4_if(ARG_CHECK_AVAILABLE, , :, ARG_CHECK_AVAILABLE)) - m4_define([ARG_CHECK_VALUE], m4_if(ARG_CHECK_VALUE, , :, ARG_CHECK_VALUE)) - m4_define([ARG_CHECK_FOR_FILES], m4_if(ARG_CHECK_FOR_FILES, , :, ARG_CHECK_FOR_FILES)) - m4_define([ARG_IF_AUTO], m4_if(ARG_IF_AUTO, , :, ARG_IF_AUTO)) - m4_define([ARG_IF_GIVEN], m4_if(ARG_IF_GIVEN, , :, ARG_IF_GIVEN)) - m4_define([ARG_IF_NOT_GIVEN], m4_if(ARG_IF_NOT_GIVEN, , :, ARG_IF_NOT_GIVEN)) + m4_if(ARG_CHECK_AVAILABLE, , [m4_define([ARG_CHECK_AVAILABLE], [:])]) + m4_if(ARG_CHECK_VALUE, , [m4_define([ARG_CHECK_VALUE], [:])]) + m4_if(ARG_CHECK_FOR_FILES, , [m4_define([ARG_CHECK_FOR_FILES], [:])]) + m4_if(ARG_IF_AUTO, , [m4_define([ARG_IF_AUTO], [:])]) + m4_if(ARG_IF_GIVEN, , [m4_define([ARG_IF_GIVEN], [:])]) + m4_if(ARG_IF_NOT_GIVEN, , [m4_define([ARG_IF_NOT_GIVEN], [:])]) ########################## # Part 2: Set up autoconf shell code @@ -813,3 +818,12 @@ AC_DEFUN([UTIL_CHECK_STRING_NON_EMPTY], FAILURE="Value cannot be empty" fi ]) + +AC_DEFUN([UTIL_CHECK_STRING_NON_EMPTY_PRINTABLE], +[ + if test "x$RESULT" = x; then + FAILURE="Value cannot be empty" + elif [ ! [[ $RESULT =~ ^[[:print:]]*$ ]] ]; then + FAILURE="Value contains non-printing characters: $RESULT" + fi +]) diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk index 802b0f130f9..ff7c90e5785 100644 --- a/make/common/JavaCompilation.gmk +++ b/make/common/JavaCompilation.gmk @@ -219,31 +219,35 @@ define SetupJavaCompilationBody # Use java server if it is enabled, and the user does not want a specialized # class path. ifeq ($$(ENABLE_JAVAC_SERVER)+$$($1_CLASSPATH), true+) - $1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_javacserver_classes javacserver.Main - # Create a configuration file with the needed information for the javac # server to function properly. - $1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-server.conf + $1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-javacserver.conf + + # Arguments needed to launch the javacserver client, as well as for the + # client to launch the server. + $1_JAVAC_SERVER_ARGS := $$(INTERIM_LANGTOOLS_ARGS) \ + -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_javacserver_classes # The portfile contains the tcp/ip on which the server listens # and the cookie necessary to talk to the server. $1_JAVAC_PORT_FILE := $$(call FixPath, $$(JAVAC_SERVER_DIR)/server.port) - # The servercmd specifies how to launch the server. This will be executed - # by the client, if needed. - $1_JAVAC_SERVER_CMD := $$(call FixPath, $$(JAVA) $$($1_JAVA_FLAGS) $$($1_JAVAC)) + # The javacmd tells the client how to run java to launch the server. + $1_JAVAC_SERVER_JAVA_CMD := $$(call FixPath, $$(JAVA) $$($1_JAVA_FLAGS) \ + $$($1_JAVAC_SERVER_ARGS)) - $1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_CMD) + $1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_JAVA_CMD) $1_CONFIG_VARDEPS_FILE := $$(call DependOnVariable, $1_CONFIG_VARDEPS, \ $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.config_vardeps) + # Write these values to a config file $$($1_JAVAC_SERVER_CONFIG): $$($1_CONFIG_VARDEPS_FILE) $(ECHO) portfile=$$($1_JAVAC_PORT_FILE) > $$@ - $(ECHO) servercmd=$$($1_JAVAC_SERVER_CMD) >> $$@ + $(ECHO) javacmd=$$($1_JAVAC_SERVER_JAVA_CMD) >> $$@ # Always use small java to launch client - $1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC) \ - --server:conf=$$($1_JAVAC_SERVER_CONFIG) + $1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC_SERVER_ARGS) \ + javacserver.Main --conf=$$($1_JAVAC_SERVER_CONFIG) else # No javac server $1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -m jdk.compiler.interim/com.sun.tools.javac.Main diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 8743f8a7619..252d9dd50da 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -306,17 +306,36 @@ endef # There are two versions, either creating a relative or an absolute link. Be # careful when using this on Windows since the symlink created is only valid in # the unix emulation environment. -define link-file-relative +# In msys2 we use mklink /J because its ln would perform a deep copy of the target. +# This inhibits performance and can lead to issues with long paths. With mklink /J +# relative linking does not work, so we handle the link as absolute path. +ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2) + define link-file-relative + $(call MakeTargetDir) + $(RM) '$(call DecodeSpace, $@)' + cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))" + endef +else + define link-file-relative $(call MakeTargetDir) $(RM) '$(call DecodeSpace, $@)' $(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)' -endef + endef +endif -define link-file-absolute +ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2) + define link-file-absolute + $(call MakeTargetDir) + $(RM) '$(call DecodeSpace, $@)' + cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))" + endef +else + define link-file-absolute $(call MakeTargetDir) $(RM) '$(call DecodeSpace, $@)' $(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' -endef + endef +endif ################################################################################ diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 3a9e5a1a57e..cf1cd2683cd 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -701,6 +701,19 @@ define SetupNativeCompilationBody $$(error No sources found for $1 when looking inside the dirs $$($1_SRC)) endif + ifeq ($$($1_TYPE), EXECUTABLE) + ifeq ($(UBSAN_ENABLED), true) + # We need to set the default options for UBSan. This needs to be included in every executable. + # Rather than copy and paste code to everything with a main function, we add an additional + # source file to every executable that exports __ubsan_default_options. + ifneq ($$(filter %.cpp %.cc, $$($1_SRCS)), ) + $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.cpp + else + $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.c + endif + endif + endif + # Calculate the expected output from compiling the sources $1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS))) $1_EXPECTED_OBJS := $$(addprefix $$($1_OBJECT_DIR)/, $$($1_EXPECTED_OBJS_FILENAMES)) diff --git a/make/common/modules/LibCommon.gmk b/make/common/modules/LibCommon.gmk index aa5c9f0a5c6..2450d2d1e03 100644 --- a/make/common/modules/LibCommon.gmk +++ b/make/common/modules/LibCommon.gmk @@ -41,15 +41,12 @@ ifeq ($(TOOLCHAIN_TYPE), gcc) CFLAGS_JDKLIB += -fvisibility=hidden CXXFLAGS_JDKLIB += -fvisibility=hidden LDFLAGS_JDKLIB += -Wl,--exclude-libs,ALL - EXPORT_ALL_SYMBOLS := -fvisibility=default else ifeq ($(TOOLCHAIN_TYPE), clang) CFLAGS_JDKLIB += -fvisibility=hidden CXXFLAGS_JDKLIB += -fvisibility=hidden - EXPORT_ALL_SYMBOLS := -fvisibility=default else ifeq ($(TOOLCHAIN_TYPE), xlc) CFLAGS_JDKLIB += -qvisibility=hidden CXXFLAGS_JDKLIB += -qvisibility=hidden - EXPORT_ALL_SYMBOLS := -qvisibility=default endif # Put the libraries here. diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index fa7062b6fa9..b7c27797034 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -26,7 +26,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) GTEST_VERSION=1.8.1 -JTREG_VERSION=7.1+1 +JTREG_VERSION=7.1.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk19/877d6127e982470ba2a7faa31cc93d04/36/GPL/openjdk-19_linux-x64_bin.tar.gz diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 4ffc7e50259..064dd7bbd32 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -944,7 +944,7 @@ var getJibProfilesProfiles = function (input, common, data) { target_cpu: input.build_cpu, dependencies: [ "jtreg", "gnumake", "boot_jdk", "devkit", "jib", "jcov", testedProfileJdk, - testedProfileTest, testedProfile + ".jdk_symbols", + testedProfileTest, ], src: "src.conf", make_args: testOnlyMake, @@ -958,6 +958,9 @@ var getJibProfilesProfiles = function (input, common, data) { labels: "test" } }; + if (!testedProfile.endsWith("-jcov")) { + testOnlyProfilesPrebuilt["run-test-prebuilt"]["dependencies"].push(testedProfile + ".jdk_symbols"); + } // If actually running the run-test-prebuilt profile, verify that the input // variable is valid and if so, add the appropriate target_* values from @@ -987,7 +990,7 @@ var getJibProfilesProfiles = function (input, common, data) { dependencies: [ "lldb" ], environment_path: [ input.get("gnumake", "install_path") + "/bin", - input.get("lldb", "install_path") + "/Xcode.app/Contents/Developer/usr/bin", + input.get("lldb", "install_path") + "/Xcode/Contents/Developer/usr/bin", ], }; profiles["run-test"] = concatObjects(profiles["run-test"], macosxRunTestExtra); @@ -1032,7 +1035,7 @@ var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { linux_x64: "gcc11.2.0-OL6.4+1.0", - macosx: "Xcode12.4+1.0", + macosx: "Xcode12.4+1.1", windows_x64: "VS2022-17.1.0+1.0", linux_aarch64: "gcc11.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", @@ -1123,7 +1126,7 @@ var getJibProfilesDependencies = function (input, common) { organization: common.organization, ext: "tar.gz", module: "devkit-macosx" + (input.build_cpu == "x64" ? "_x64" : ""), - revision: (input.build_cpu == "x64" ? "Xcode11.3.1-MacOSX10.15+1.1" : devkit_platform_revisions[devkit_platform]) + revision: (input.build_cpu == "x64" ? "Xcode11.3.1-MacOSX10.15+1.2" : devkit_platform_revisions[devkit_platform]) }, cups: { @@ -1135,9 +1138,9 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "jpg", product: "jtreg", - version: "7.1", + version: "7.1.1", build_number: "1", - file: "bundles/jtreg-7.1+1.zip", + file: "bundles/jtreg-7.1.1+1.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "home_path") + "/bin", configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"), @@ -1151,7 +1154,7 @@ var getJibProfilesDependencies = function (input, common) { jcov: { organization: common.organization, - revision: "3.0-13-jdk-asm+1.0", + revision: "3.0-14-jdk-asm+1.0", ext: "zip", environment_name: "JCOV_HOME", }, diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 5be559266fe..4a3e5133567 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -26,17 +26,17 @@ # Default version, product, and vendor information to use, # unless overridden by configure -DEFAULT_VERSION_FEATURE=20 +DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 DEFAULT_VERSION_UPDATE=0 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2023-03-21 -DEFAULT_VERSION_CLASSFILE_MAJOR=64 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" +DEFAULT_VERSION_DATE=2023-09-19 +DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="19 20" -DEFAULT_JDK_SOURCE_TARGET_VERSION=20 +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="19 20 21" +DEFAULT_JDK_SOURCE_TARGET_VERSION=21 DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/make/data/cldr/common/bcp47/timezone.xml b/make/data/cldr/common/bcp47/timezone.xml index ddbccff077c..57d81ed48ec 100644 --- a/make/data/cldr/common/bcp47/timezone.xml +++ b/make/data/cldr/common/bcp47/timezone.xml @@ -280,6 +280,7 @@ For terms of use, see http://www.unicode.org/copyright.html + diff --git a/make/data/cldr/common/main/root.xml b/make/data/cldr/common/main/root.xml index 411a316f8ed..44c80ff1348 100644 --- a/make/data/cldr/common/main/root.xml +++ b/make/data/cldr/common/main/root.xml @@ -2994,6 +2994,18 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ Ho Chi Minh + + Bahía de Banderas + + + Cancún + + + Ciudad Juárez + + + Mérida + diff --git a/make/data/cldr/common/supplemental/metaZones.xml b/make/data/cldr/common/supplemental/metaZones.xml index 1c363cbe7aa..0beb757cacb 100644 --- a/make/data/cldr/common/supplemental/metaZones.xml +++ b/make/data/cldr/common/supplemental/metaZones.xml @@ -333,6 +333,12 @@ For terms of use, see http://www.unicode.org/copyright.html + + + + + + @@ -621,8 +627,7 @@ For terms of use, see http://www.unicode.org/copyright.html - - + diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index de2babed51a..ae49a992f54 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -194,8 +194,6 @@ JVM_RegisterLambdaProxyClassForArchiving JVM_RegisterSignal JVM_ReleaseUTF JVM_ReportFinalizationComplete -JVM_ExtentLocalCache -JVM_SetExtentLocalCache JVM_SetArrayElement JVM_SetClassSigners JVM_SetNativeThreadName @@ -225,4 +223,10 @@ JVM_VirtualThreadMountEnd JVM_VirtualThreadUnmountBegin JVM_VirtualThreadUnmountEnd JVM_VirtualThreadHideFrames + +# Scoped values +JVM_EnsureMaterializedForStackWalk_func +JVM_FindScopedValueBindings +JVM_ScopedValueCache +JVM_SetScopedValueCache # diff --git a/make/data/ubsan/ubsan_default_options.c b/make/data/ubsan/ubsan_default_options.c new file mode 100644 index 00000000000..ee426ebbc39 --- /dev/null +++ b/make/data/ubsan/ubsan_default_options.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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. 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. + */ + +#ifndef UNDEFINED_BEHAVIOR_SANITIZER +#error "Build misconfigured, preprocessor macro UNDEFINED_BEHAVIOR_SANITIZER should be defined" +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(visibility) +#define ATTRIBUTE_DEFAULT_VISIBILITY __attribute__((visibility("default"))) +#else +#define ATTRIBUTE_DEFAULT_VISIBILITY +#endif + +#if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(used) +#define ATTRIBUTE_USED __attribute__((used)) +#else +#define ATTRIBUTE_USED +#endif + +// Override weak symbol exposed by UBSan to override default options. This is called by UBSan +// extremely early during library loading, before main is called. We need to override the default +// options because by default UBSan only prints a warning for each occurrence. We want jtreg tests +// to fail when undefined behavior is encountered. We also want a full stack trace for the offending +// thread so it is easier to track down. You can override these options by setting the environment +// variable UBSAN_OPTIONS. +ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __ubsan_default_options() { + return "halt_on_error=1,print_stacktrace=1"; +} diff --git a/make/data/ubsan/ubsan_default_options.cpp b/make/data/ubsan/ubsan_default_options.cpp new file mode 100644 index 00000000000..dbebb5b2977 --- /dev/null +++ b/make/data/ubsan/ubsan_default_options.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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. 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. + */ + +extern "C" { + +#include "./ubsan_default_options.c" + +} // extern "C" diff --git a/make/hotspot/lib/JvmFlags.gmk b/make/hotspot/lib/JvmFlags.gmk index 1588c19fac3..1fadd5331aa 100644 --- a/make/hotspot/lib/JvmFlags.gmk +++ b/make/hotspot/lib/JvmFlags.gmk @@ -67,10 +67,12 @@ JVM_CFLAGS_TARGET_DEFINES += \ # ifeq ($(DEBUG_LEVEL), release) + # release builds disable uses of assert macro from . + JVM_CFLAGS_DEBUGLEVEL := -DNDEBUG # For hotspot, release builds differ internally between "optimized" and "product" # in that "optimize" does not define PRODUCT. ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) - JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT + JVM_CFLAGS_DEBUGLEVEL += -DPRODUCT endif else ifeq ($(DEBUG_LEVEL), fastdebug) JVM_CFLAGS_DEBUGLEVEL := -DASSERT diff --git a/make/hotspot/test/GtestImage.gmk b/make/hotspot/test/GtestImage.gmk index 322a90b3d10..d216328e567 100644 --- a/make/hotspot/test/GtestImage.gmk +++ b/make/hotspot/test/GtestImage.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 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 @@ -41,10 +41,22 @@ ifeq ($(call isTargetOs, windows), true) $(foreach v, $(JVM_VARIANTS), \ $(eval $(call SetupCopyFiles, COPY_GTEST_MSVCR_$v, \ DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \ - FILES := $(MSVCR_DLL) $(VCRUNTIME_1_DLL) $(MSVCP_DLL), \ + FILES := $(MSVCR_DLL), \ FLATTEN := true, \ )) \ $(eval TARGETS += $$(COPY_GTEST_MSVCR_$v)) \ + $(eval $(call SetupCopyFiles, COPY_GTEST_VCRUNTIME_1_$v, \ + DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \ + FILES := $(VCRUNTIME_1_DLL), \ + FLATTEN := true, \ + )) \ + $(eval TARGETS += $$(COPY_GTEST_VCRUNTIME_1_$v)) \ + $(eval $(call SetupCopyFiles, COPY_GTEST_MSVCP_$v, \ + DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \ + FILES := $(MSVCP_DLL), \ + FLATTEN := true, \ + )) \ + $(eval TARGETS += $$(COPY_GTEST_MSVCP_$v)) \ $(if $(call equals, $(COPY_DEBUG_SYMBOLS), true), \ $(eval $(call SetupCopyFiles, COPY_GTEST_PDB_$v, \ SRC := $(HOTSPOT_OUTPUTDIR)/variant-$v/libjvm/gtest, \ diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index e0e95c9e6a2..d6c502252e0 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,8 +34,6 @@ import java.time.*; import java.util.*; import java.util.ResourceBundle.Control; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -609,16 +607,19 @@ private static void convertBundles(List bundles) throws Exception { * Translate the aliases into the real entries in the bundle map. */ static void handleAliases(Map bundleMap) { - Set bundleKeys = bundleMap.keySet(); - try { - for (String key : aliases.keySet()) { - String targetKey = aliases.get(key); - if (bundleKeys.contains(targetKey)) { - bundleMap.putIfAbsent(key, bundleMap.get(targetKey)); + for (String key : aliases.keySet()) { + var source = bundleMap.get(aliases.get(key)); + if (source != null) { + if (bundleMap.get(key) instanceof String[] sa) { + // fill missing elements in case of String array + for (int i = 0; i < sa.length; i++) { + if (sa[i] == null && ((String[])source)[i] != null) { + sa[i] = ((String[])source)[i]; + } + } } + bundleMap.putIfAbsent(key, source); } - } catch (Exception ex) { - Logger.getLogger(CLDRConverter.class.getName()).log(Level.SEVERE, null, ex); } } @@ -633,7 +634,7 @@ static String getLanguageCode(String id) { /** * Examine if the id includes the country (territory) code. If it does, it returns * the country code. - * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". + * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it returns "SG". * It does NOT return UN M.49 code, e.g., '001', as those three digit numbers cannot * be translated into package names. */ @@ -645,13 +646,21 @@ static String getCountryCode(String id) { /** * Examine if the id includes the region code. If it does, it returns * the region code. - * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". + * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it returns "SG". * It DOES return UN M.49 code, e.g., '001', as well as ISO 3166 two letter country codes. */ static String getRegionCode(String id) { return Locale.forLanguageTag(id.replaceAll("_", "-")).getCountry(); } + /** + * Examine if the id includes the script code. If it does, it returns + * the script code. + */ + static String getScriptCode(String id) { + return Locale.forLanguageTag(id.replaceAll("_", "-")).getScript(); + } + private static class KeyComparator implements Comparator { static KeyComparator INSTANCE = new KeyComparator(); @@ -1020,6 +1029,7 @@ private static String toLocaleName(String tag) { private static void setupBaseLocales(String localeList) { Arrays.stream(localeList.split(",")) .map(Locale::forLanguageTag) + .map(l -> new Locale.Builder().setLocale(l).setScript("Latn").build()) .map(l -> Control.getControl(Control.FORMAT_DEFAULT) .getCandidateLocales("", l)) .forEach(BASE_LOCALES::addAll); diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 344bb0ea21f..6b2b5b4c0c0 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -417,11 +417,11 @@ public Map parentLocales() { private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder(); private static boolean isBaseLocale(String localeID) { localeID = localeID.replaceAll("-", "_"); - // ignore script here Locale locale = LOCALE_BUILDER .clear() .setLanguage(CLDRConverter.getLanguageCode(localeID)) .setRegion(CLDRConverter.getRegionCode(localeID)) + .setScript(CLDRConverter.getScriptCode(localeID)) .build(); return CLDRConverter.BASE_LOCALES.contains(locale); } diff --git a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java index da79c17b387..df719d6fce6 100644 --- a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java @@ -40,6 +40,7 @@ import static java.lang.System.lineSeparator; import static java.nio.file.StandardOpenOption.*; +import static java.util.stream.Collectors.joining; import static jdk.javadoc.doclet.Taglet.Location.TYPE; /** @@ -98,7 +99,7 @@ public String toString(List tags, Element element) { .map(Objects::toString) .collect(Collectors.toUnmodifiableSet()); - String dotContent = Renderer.graph(typeElement, exports); + String dotContent = new Renderer().graph(typeElement, exports); try { Files.writeString(dotFile, dotContent, WRITE, CREATE, TRUNCATE_EXISTING); @@ -133,13 +134,10 @@ private String getImage(String typeName, String file, int height, boolean useBor (height <= 0 ? "" : " height=\"" + height + "\"")); } - private static final class Renderer { - - private Renderer() { - } + private final class Renderer { // Generates a graph in DOT format - static String graph(TypeElement rootClass, Set exports) { + String graph(TypeElement rootClass, Set exports) { final State state = new State(rootClass); traverse(state, rootClass, exports); return state.render(); @@ -155,17 +153,21 @@ static void traverse(State state, TypeElement node, Set exports) { } } - private static final class State { + private final class State { private static final String LABEL = "label"; private static final String TOOLTIP = "tooltip"; + private static final String LINK = "href"; private static final String STYLE = "style"; + private final TypeElement rootNode; + private final StringBuilder builder; private final Map> nodeStyleMap; public State(TypeElement rootNode) { + this.rootNode = rootNode; nodeStyleMap = new LinkedHashMap<>(); builder = new StringBuilder() .append("digraph G {") @@ -188,12 +190,30 @@ public void addNode(TypeElement node) { var styles = nodeStyleMap.computeIfAbsent(id(node), n -> new LinkedHashMap<>()); styles.put(LABEL, node.getSimpleName().toString()); styles.put(TOOLTIP, node.getQualifiedName().toString()); + styles.put(LINK, relativeLink(node)); if (!(node.getModifiers().contains(Modifier.SEALED) || node.getModifiers().contains(Modifier.FINAL))) { // This indicates that the hierarchy is not closed styles.put(STYLE, "dashed"); } } + // A permitted class must be in the same package or in the same module. + // This implies the module is always the same. + private String relativeLink(TypeElement node) { + var util = SealedGraph.this.docletEnvironment.getElementUtils(); + var rootPackage = util.getPackageOf(rootNode); + var nodePackage = util.getPackageOf(node); + var backNavigator = rootPackage.getQualifiedName().toString().chars() + .filter(c -> c == '.') + .mapToObj(c -> "../") + .collect(joining()) + + "../"; + var forwardNavigator = nodePackage.getQualifiedName().toString() + .replace(".", "/"); + + return backNavigator + forwardNavigator + "/" + node.getSimpleName() + ".html"; + } + public void addEdge(TypeElement node, TypeElement subNode) { builder.append(" ") .append(quotedId(subNode)) @@ -209,8 +229,8 @@ public String render() { .append('"').append(nodeName).append("\" ") .append(styles.entrySet().stream() .map(e -> e.getKey() + "=\"" + e.getValue() + "\"") - .collect(Collectors.joining(" ", "[", "]"))) - .append(System.lineSeparator()); + .collect(joining(" ", "[", "]"))) + .append(lineSeparator()); }); builder.append("}"); return builder.toString(); diff --git a/make/langtools/tools/javacserver/Main.java b/make/langtools/tools/javacserver/Main.java index 2eecfb2b4a8..b2582518948 100644 --- a/make/langtools/tools/javacserver/Main.java +++ b/make/langtools/tools/javacserver/Main.java @@ -25,34 +25,13 @@ package javacserver; -import java.util.Arrays; - -import javacserver.client.ClientMain; -import javacserver.server.ServerMain; - -import static javacserver.options.Option.STARTSERVER; +import javacserver.client.Client; /** - * The application entry point of the smart javac wrapper tool. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * The application entry point of the javacserver build tool. */ public class Main { - - public static void main(String... args) { - System.exit(go(args)); - } - - public static int go(String[] args) { - - // Server or client mode? - boolean serverMode = Arrays.asList(args) - .stream() - .anyMatch(arg -> arg.startsWith(STARTSERVER.arg)); - - return serverMode ? ServerMain.run(args) : ClientMain.run(args); + public static void main(String... args) { + Client.main(args); } } diff --git a/make/langtools/tools/javacserver/Util.java b/make/langtools/tools/javacserver/Util.java deleted file mode 100644 index 96558d503c8..00000000000 --- a/make/langtools/tools/javacserver/Util.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2012, 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. 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 javacserver; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -/** - * Utilities. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Util { - - - - public static String extractStringOption(String opName, String s) { - return extractStringOption(opName, s, null); - } - - private static String extractStringOptionWithDelimiter(String opName, String s, String deflt, char delimiter) { - int p = s.indexOf(opName+"="); - if (p == -1) return deflt; - p+=opName.length()+1; - int pe = s.indexOf(delimiter, p); - if (pe == -1) pe = s.length(); - return s.substring(p, pe); - } - - public static String extractStringOption(String opName, String s, String deflt) { - return extractStringOptionWithDelimiter(opName, s, deflt, ','); - } - - public static String extractStringOptionLine(String opName, String s, String deflt) { - return extractStringOptionWithDelimiter(opName, s, deflt, '\n').strip(); - } - - public static int extractIntOption(String opName, String s, int deflt) { - int p = s.indexOf(opName+"="); - if (p == -1) return deflt; - p+=opName.length()+1; - int pe = s.indexOf(',', p); - if (pe == -1) pe = s.length(); - int v = 0; - try { - v = Integer.parseInt(s.substring(p, pe)); - } catch (Exception e) {} - return v; - } - - - /** - * Convenience method to create a set with strings. - */ - public static Set set(String... ss) { - Set set = new HashSet<>(); - set.addAll(Arrays.asList(ss)); - return set; - } - - /** - * Normalize windows drive letter paths to upper case to enable string - * comparison. - * - * @param file File name to normalize - * @return The normalized string if file has a drive letter at the beginning, - * otherwise the original string. - */ - public static String normalizeDriveLetter(String file) { - if (file.length() > 2 && file.charAt(1) == ':') { - return Character.toUpperCase(file.charAt(0)) + file.substring(1); - } else if (file.length() > 3 && file.charAt(0) == '*' - && file.charAt(2) == ':') { - // Handle a wildcard * at the beginning of the string. - return file.substring(0, 1) + Character.toUpperCase(file.charAt(1)) - + file.substring(2); - } - return file; - } - - - public static Set union(Set s1, - Set s2) { - Set union = new HashSet<>(); - union.addAll(s1); - union.addAll(s2); - return union; - } - - public static Set subtract(Set orig, - Set toSubtract) { - Set difference = new HashSet<>(orig); - difference.removeAll(toSubtract); - return difference; - } - - public static String getStackTrace(Throwable t) { - StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - return sw.toString(); - } - - public static Set intersection(Collection c1, - Collection c2) { - Set intersection = new HashSet(c1); - intersection.retainAll(c2); - return intersection; - } - - - public static Stream getLines(String str) { - return str.isEmpty() - ? Stream.empty() - : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); - } -} diff --git a/make/langtools/tools/javacserver/client/Client.java b/make/langtools/tools/javacserver/client/Client.java new file mode 100644 index 00000000000..b3b4a8543a0 --- /dev/null +++ b/make/langtools/tools/javacserver/client/Client.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2014, 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. 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 javacserver.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javacserver.server.Server; +import javacserver.shared.PortFileInaccessibleException; +import javacserver.shared.Protocol; +import javacserver.shared.Result; +import javacserver.util.AutoFlushWriter; +import javacserver.util.Log; + +/** + * The javacserver client. This is called from the makefiles, and is responsible for passing the command + * line on to a server instance running javac, starting a new server if needed. + */ +public class Client { + private static final Log.Level LOG_LEVEL = Log.Level.INFO; + + // Wait 2 seconds for response, before giving up on javac server. + private static final int CONNECTION_TIMEOUT = 2000; + private static final int MAX_CONNECT_ATTEMPTS = 3; + private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; + + private final ClientConfiguration conf; + + public Client(ClientConfiguration conf) { + this.conf = conf; + } + + public static void main(String... args) { + Log.setLogForCurrentThread(new Log( + new AutoFlushWriter(new OutputStreamWriter(System.out)), + new AutoFlushWriter(new OutputStreamWriter(System.err)))); + Log.setLogLevel(LOG_LEVEL); + + ClientConfiguration conf = ClientConfiguration.fromCommandLineArguments(args); + if (conf == null) { + System.exit(Result.CMDERR.exitCode); + } + + Client client = new Client(conf); + int exitCode = client.dispatchToServer(); + + System.exit(exitCode); + } + + private int dispatchToServer() { + try { + // Check if server seems to be already running + if (!conf.portFile().hasValidValues()) { + // Fork a new server and wait for it to start + startNewServer(); + } + + try (Socket socket = tryConnect()) { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); + + Protocol.sendCommand(out, conf.javacArgs()); + int exitCode = Protocol.readResponse(in); + + return exitCode; + } + } catch (PortFileInaccessibleException e) { + Log.error("Port file inaccessible."); + return Result.ERROR.exitCode; + } catch (IOException ioe) { + Log.error("IOException caught during compilation: " + ioe.getMessage()); + Log.debug(ioe); + return Result.ERROR.exitCode; + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); // Restore interrupt + Log.error("Compilation interrupted."); + Log.debug(ie); + return Result.ERROR.exitCode; + } + } + + /* + * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server. + */ + private Socket tryConnect() throws IOException, InterruptedException { + int attempt = 0; + + while (true) { + Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS); + try { + Socket socket = new Socket(); + InetAddress localhost = InetAddress.getByName(null); + InetSocketAddress address = new InetSocketAddress(localhost, conf.portFile().getPort()); + socket.connect(address, CONNECTION_TIMEOUT); + Log.debug("Connected"); + return socket; + } catch (IOException ex) { + Log.error("Connection attempt failed: " + ex.getMessage()); + if (attempt >= MAX_CONNECT_ATTEMPTS) { + Log.error("Giving up"); + throw new IOException("Could not connect to server", ex); + } + } + Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); + } + } + + /* + * Fork a server process and wait for server to come around + */ + private void startNewServer() throws IOException, InterruptedException { + List cmd = new ArrayList<>(); + // conf.javaCommand() is how to start java in the way we want to run + // the server + cmd.addAll(Arrays.asList(conf.javaCommand().split(" "))); + // javacserver.server.Server is the server main class + cmd.add(Server.class.getName()); + // and it expects a port file path + cmd.add(conf.portFile().getFilename()); + + Process serverProcess; + Log.debug("Starting server. Command: " + String.join(" ", cmd)); + try { + // If the cmd for some reason can't be executed (file is not found, + // or is not executable for instance) this will throw an + // IOException + serverProcess = new ProcessBuilder(cmd).redirectErrorStream(true).start(); + } catch (IOException ex) { + // Message is typically something like: + // Cannot run program "xyz": error=2, No such file or directory + Log.error("Failed to create server process: " + ex.getMessage()); + Log.debug(ex); + throw new IOException(ex); + } + + // serverProcess != null at this point. + try { + // Throws an IOException if no valid values materialize + conf.portFile().waitForValidValues(); + } catch (IOException ex) { + // Process was started, but server failed to initialize. This could + // for instance be due to the JVM not finding the server class, + // or the server running in to some exception early on. + Log.error("javacserver server process failed to initialize: " + ex.getMessage()); + Log.error("Process output:"); + Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); + try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { + br.lines().forEach(Log::error); + } + Log.error(""); + try { + Log.error("Process exit code: " + serverProcess.exitValue()); + } catch (IllegalThreadStateException e) { + // Server is presumably still running. + } + throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); + } + } +} diff --git a/make/langtools/tools/javacserver/client/ClientConfiguration.java b/make/langtools/tools/javacserver/client/ClientConfiguration.java new file mode 100644 index 00000000000..1c901d615f3 --- /dev/null +++ b/make/langtools/tools/javacserver/client/ClientConfiguration.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014, 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. 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 javacserver.client; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import javacserver.shared.PortFile; +import javacserver.util.Log; + +/** + * Description of the arguments needed to start a javacserver client, as extracted from + * the command line and configuration file. + */ +public record ClientConfiguration(PortFile portFile, String javaCommand, String[] javacArgs) { + static ClientConfiguration fromCommandLineArguments(String... args) { + String confFileName = getConfFileName(args); + if (confFileName == null) { + return null; + } + + String confFileContent = getConfFileContent(confFileName); + if (confFileContent == null) { + return null; + } + + String portFileName = getPortFileName(confFileContent); + if (portFileName == null) { + return null; + } + String javaCommand = getJavaCommandString(confFileContent); + if (javaCommand == null) { + return null; + } + + PortFile portFile = new PortFile(portFileName); + String[] javacArgs = Arrays.copyOfRange(args, 1, args.length); + + ClientConfiguration conf = new ClientConfiguration(portFile, javaCommand, javacArgs); + return conf; + } + + private static String getConfFileName(String[] args) { + if (args.length < 1) { + Log.error("Error: javacserver client: missing --conf= argument"); + return null; + } + String[] conf = args[0].split("=", 2); + if (conf.length != 2 || !conf[0].equalsIgnoreCase("--conf")) { + Log.error("Error: javacserver client: first argument must be --conf="); + return null; + } + String confFileName = conf[1]; + if (!Files.exists(Path.of(confFileName))) { + Log.error("Error: javacserver client: specified conf file does not exist"); + return null; + } + return confFileName; + } + + private static String getConfFileContent(String confFile) { + try { + List confFileLines = Files.readAllLines(Path.of(confFile)); + String confFileContent = String.join("\n", confFileLines); + return confFileContent; + } catch (IOException e) { + Log.error("Cannot read configuration file " + confFile); + Log.debug(e); + return null; + } + } + + private static String getJavaCommandString(String confFileContent) { + String serverCommandString = getConfValue("javacmd", confFileContent); + if (serverCommandString.isEmpty()) { + Log.error("Configuration file missing value for 'javacmd'"); + return null; + } else { + return serverCommandString; + } + } + + private static String getPortFileName(String confFileContent) { + String portfileName = getConfValue("portfile", confFileContent); + if (portfileName.isEmpty()) { + Log.error("Configuration file missing value for 'portfile'"); + return null; + } else { + return portfileName; + } + } + + private static String getConfValue(String optionName, String content) { + String result; + int p = content.indexOf(optionName + "="); + if (p == -1) { + result = ""; + } else { + p += optionName.length() + 1; + int pe = content.indexOf('\n', p); + if (pe == -1) pe = content.length(); + result = content.substring(p, pe); + } + return result.strip(); + } +} \ No newline at end of file diff --git a/make/langtools/tools/javacserver/client/ClientMain.java b/make/langtools/tools/javacserver/client/ClientMain.java deleted file mode 100644 index c26ead5e633..00000000000 --- a/make/langtools/tools/javacserver/client/ClientMain.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.client; - -import java.io.OutputStreamWriter; -import java.io.Writer; - -import javacserver.AutoFlushWriter; -import javacserver.Log; -import javacserver.Result; -import javacserver.comp.SjavacImpl; -import javacserver.options.Options; -import javacserver.server.Sjavac; - -/** - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClientMain { - - public static int run(String[] args) { - return run(args, - new AutoFlushWriter(new OutputStreamWriter(System.out)), - new AutoFlushWriter(new OutputStreamWriter(System.err))); - } - - public static int run(String[] args, Writer out, Writer err) { - - Log.setLogForCurrentThread(new Log(out, err)); - - Options options; - try { - options = Options.parseArgs(args); - } catch (IllegalArgumentException e) { - Log.error(e.getMessage()); - return Result.CMDERR.exitCode; - } - - Log.setLogLevel(options.getLogLevel()); - - // Prepare sjavac object - boolean useServer = options.getServerConf() != null; - Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); - - // Perform compilation - Result result = sjavac.compile(args); - - // If sjavac is running in the foreground we should shut it down at this point - if (!useServer) { - sjavac.shutdown(); - } - - return result.exitCode; - } -} diff --git a/make/langtools/tools/javacserver/client/SjavacClient.java b/make/langtools/tools/javacserver/client/SjavacClient.java deleted file mode 100644 index 3d12eb31782..00000000000 --- a/make/langtools/tools/javacserver/client/SjavacClient.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.Reader; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.options.Options; -import javacserver.server.PortFile; -import javacserver.server.Sjavac; -import javacserver.server.SjavacServer; - -/** - * Sjavac implementation that delegates requests to a SjavacServer. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacClient implements Sjavac { - - private PortFile portFile; - - // The servercmd option specifies how the server part of sjavac is spawned. - // It should point to a javacserver.Main that supports --startserver - private String serverCommand; - - // Accept 120 seconds of inactivity before quitting. - private static final int KEEPALIVE = 120; - private static final int POOLSIZE = Runtime.getRuntime().availableProcessors(); - // Wait 2 seconds for response, before giving up on javac server. - private static final int CONNECTION_TIMEOUT = 2000; - private static final int MAX_CONNECT_ATTEMPTS = 3; - private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; - - public SjavacClient(Options options) { - String serverConf = options.getServerConf(); - String configFile = Util.extractStringOption("conf", serverConf, ""); - - try { - List configFileLines = Files.readAllLines(Path.of(configFile)); - String configFileContent = String.join("\n", configFileLines); - - String portfileName = Util.extractStringOptionLine("portfile", configFileContent, ""); - if (portfileName.isEmpty()) { - Log.error("Configuration file missing value for 'portfile'"); - portFile = null; - } else { - portFile = SjavacServer.getPortFile(portfileName); - } - - String serverCommandString = Util.extractStringOptionLine("servercmd", configFileContent, ""); - if (serverCommandString.isEmpty()) { - Log.error("Configuration file missing value for 'servercmd'"); - serverCommand = null; - } else { - serverCommand = serverCommandString; - } - } catch (IOException e) { - Log.error("Cannot read configuration file " + configFile); - Log.debug(e); - portFile = null; - serverCommand = null; - } - } - - @Override - public Result compile(String[] args) { - if (portFile == null || serverCommand == null) { - Log.error("Incorrect configuration, portfile and/or servercmd missing"); - return Result.ERROR; - } - - Result result = null; - try (Socket socket = tryConnect()) { - PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - // Send args array to server - out.println(args.length); - for (String arg : args) - out.println(arg); - out.flush(); - - // Read server response line by line - String line; - while (null != (line = in.readLine())) { - if (!line.contains(":")) { - throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); - } - String[] typeAndContent = line.split(":", 2); - String type = typeAndContent[0]; - String content = typeAndContent[1]; - - try { - if (Log.isDebugging()) { - // Distinguish server generated output if debugging. - content = "[sjavac-server] " + content; - } - Log.log(Log.Level.valueOf(type), content); - continue; - } catch (IllegalArgumentException e) { - // Parsing of 'type' as log level failed. - } - - if (type.equals(SjavacServer.LINE_TYPE_RC)) { - result = Result.valueOf(content); - } - } - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessible."); - result = Result.ERROR; - } catch (IOException ioe) { - Log.error("IOException caught during compilation: " + ioe.getMessage()); - Log.debug(ioe); - result = Result.ERROR; - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); // Restore interrupt - Log.error("Compilation interrupted."); - Log.debug(ie); - result = Result.ERROR; - } - - if (result == null) { - // No LINE_TYPE_RC was found. - result = Result.ERROR; - } - - return result; - } - - /* - * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server. - */ - private Socket tryConnect() throws IOException, InterruptedException { - makeSureServerIsRunning(); - int attempt = 0; - while (true) { - Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS); - try { - return makeConnectionAttempt(); - } catch (IOException ex) { - Log.error("Connection attempt failed: " + ex.getMessage()); - if (attempt >= MAX_CONNECT_ATTEMPTS) { - Log.error("Giving up"); - throw new IOException("Could not connect to server", ex); - } - } - Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); - } - } - - private Socket makeConnectionAttempt() throws IOException { - Socket socket = new Socket(); - InetAddress localhost = InetAddress.getByName(null); - InetSocketAddress address = new InetSocketAddress(localhost, portFile.getPort()); - socket.connect(address, CONNECTION_TIMEOUT); - Log.debug("Connected"); - return socket; - } - - /* - * Will return immediately if a server already seems to be running, - * otherwise fork a new server and block until it seems to be running. - */ - private void makeSureServerIsRunning() - throws IOException, InterruptedException { - - if (portFile.exists()) { - portFile.lock(); - portFile.getValues(); - portFile.unlock(); - - if (portFile.containsPortInfo()) { - // Server seems to already be running - return; - } - } - - // Fork a new server and wait for it to start - startNewServer(); - } - - @Override - public void shutdown() { - // Nothing to clean up - } - - /* - * Fork a server process process and wait for server to come around - */ - public void startNewServer() - throws IOException, InterruptedException { - List cmd = new ArrayList<>(); - cmd.addAll(Arrays.asList(serverCommand.split(" "))); - cmd.add("--startserver:" - + "portfile=" + portFile.getFilename() - + ",poolsize=" + POOLSIZE - + ",keepalive="+ KEEPALIVE); - - Process serverProcess; - Log.debug("Starting server. Command: " + String.join(" ", cmd)); - try { - // If the cmd for some reason can't be executed (file is not found, - // or is not executable for instance) this will throw an - // IOException and p == null. - serverProcess = new ProcessBuilder(cmd) - .redirectErrorStream(true) - .start(); - } catch (IOException ex) { - // Message is typically something like: - // Cannot run program "xyz": error=2, No such file or directory - Log.error("Failed to create server process: " + ex.getMessage()); - Log.debug(ex); - throw new IOException(ex); - } - - // serverProcess != null at this point. - try { - // Throws an IOException if no valid values materialize - portFile.waitForValidValues(); - } catch (IOException ex) { - // Process was started, but server failed to initialize. This could - // for instance be due to the JVM not finding the server class, - // or the server running in to some exception early on. - Log.error("Sjavac server failed to initialize: " + ex.getMessage()); - Log.error("Process output:"); - Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); - try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { - br.lines().forEach(Log::error); - } - Log.error(""); - try { - Log.error("Process exit code: " + serverProcess.exitValue()); - } catch (IllegalThreadStateException e) { - // Server is presumably still running. - } - throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); - } - } -} diff --git a/make/langtools/tools/javacserver/comp/SjavacImpl.java b/make/langtools/tools/javacserver/comp/SjavacImpl.java deleted file mode 100644 index eb7ba30f73d..00000000000 --- a/make/langtools/tools/javacserver/comp/SjavacImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.comp; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.stream.Stream; - -import com.sun.tools.javac.Main; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.options.Option; -import javacserver.server.Sjavac; - -/** - * The sjavac implementation that interacts with javac and performs the actual - * compilation. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacImpl implements Sjavac { - - @Override - @SuppressWarnings("deprecated") - public Result compile(String[] args) { - // Direct logging to our byte array stream. - StringWriter strWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(strWriter); - - // Prepare arguments - String[] passThroughArgs = Stream.of(args) - .filter(arg -> !arg.startsWith(Option.SERVER.arg)) - .toArray(String[]::new); - // Compile - int exitcode = Main.compile(passThroughArgs, printWriter); - Result result = Result.of(exitcode); - - // Process compiler output (which is always errors) - printWriter.flush(); - Util.getLines(strWriter.toString()).forEach(Log::error); - - return result; - - } - - @Override - public void shutdown() { - // Nothing to clean up - } -} diff --git a/make/langtools/tools/javacserver/options/ArgumentIterator.java b/make/langtools/tools/javacserver/options/ArgumentIterator.java deleted file mode 100644 index 54c6105227a..00000000000 --- a/make/langtools/tools/javacserver/options/ArgumentIterator.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.options; - -import java.util.Iterator; - -/** - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ArgumentIterator implements Iterator { - - /** The underlying argument iterator */ - private Iterator iter; - - /** Extra state used to implement peek and current */ - private String current; - private String buffered; - - public ArgumentIterator(Iterable iter) { - this.iter = iter.iterator(); - } - - @Override - public boolean hasNext() { - return buffered != null || iter.hasNext(); - } - - @Override - public String next() { - fillBuffer(); - current = buffered; - buffered = null; - return current; - } - - /** - * @return the last element returned by next() (or {@code null} if next has - * never been invoked on this iterator). - */ - public String current() { - return current; - } - - /** Can't remove current element, since we may have buffered it. */ - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - /** - * @return Returns the next element without advancing the iterator - */ - public String peek() { - fillBuffer(); - return buffered; - } - - private void fillBuffer() { - if (buffered == null && iter.hasNext()) - buffered = iter.next(); - } - -} diff --git a/make/langtools/tools/javacserver/options/CommandLine.java b/make/langtools/tools/javacserver/options/CommandLine.java deleted file mode 100644 index 017d32a0d7c..00000000000 --- a/make/langtools/tools/javacserver/options/CommandLine.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 1999, 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. 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 javacserver.options; - -import java.io.IOException; -import java.io.Reader; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -/** - * Various utility methods for processing Java tool command line arguments. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class CommandLine { - /** - * Process Win32-style command files for the specified command line - * arguments and return the resulting arguments. A command file argument - * is of the form '@file' where 'file' is the name of the file whose - * contents are to be parsed for additional arguments. The contents of - * the command file are parsed using StreamTokenizer and the original - * '@file' argument replaced with the resulting tokens. Recursive command - * files are not supported. The '@' character itself can be quoted with - * the sequence '@@'. - * @param args the arguments that may contain @files - * @return the arguments, with @files expanded - * @throws IOException if there is a problem reading any of the @files - */ - public static List parse(List args) throws IOException { - List newArgs = new ArrayList<>(); - appendParsedCommandArgs(newArgs, args); - return newArgs; - } - - private static void appendParsedCommandArgs(List newArgs, List args) throws IOException { - for (String arg : args) { - if (arg.length() > 1 && arg.charAt(0) == '@') { - arg = arg.substring(1); - if (arg.charAt(0) == '@') { - newArgs.add(arg); - } else { - loadCmdFile(arg, newArgs); - } - } else { - newArgs.add(arg); - } - } - } - - /** - * Process the given environment variable and appends any Win32-style - * command files for the specified command line arguments and return - * the resulting arguments. A command file argument - * is of the form '@file' where 'file' is the name of the file whose - * contents are to be parsed for additional arguments. The contents of - * the command file are parsed using StreamTokenizer and the original - * '@file' argument replaced with the resulting tokens. Recursive command - * files are not supported. The '@' character itself can be quoted with - * the sequence '@@'. - * @param envVariable the env variable to process - * @param args the arguments that may contain @files - * @return the arguments, with environment variable's content and expansion of @files - * @throws IOException if there is a problem reading any of the @files - * @throws UnmatchedQuote - */ - public static List parse(String envVariable, List args) - throws IOException, UnmatchedQuote { - - List inArgs = new ArrayList<>(); - appendParsedEnvVariables(inArgs, envVariable); - inArgs.addAll(args); - List newArgs = new ArrayList<>(); - appendParsedCommandArgs(newArgs, inArgs); - return newArgs; - } - - private static void loadCmdFile(String name, List args) throws IOException { - try (Reader r = Files.newBufferedReader(Paths.get(name), Charset.defaultCharset())) { - Tokenizer t = new Tokenizer(r); - String s; - while ((s = t.nextToken()) != null) { - args.add(s); - } - } - } - - public static class Tokenizer { - private final Reader in; - private int ch; - - public Tokenizer(Reader in) throws IOException { - this.in = in; - ch = in.read(); - } - - public String nextToken() throws IOException { - skipWhite(); - if (ch == -1) { - return null; - } - - StringBuilder sb = new StringBuilder(); - char quoteChar = 0; - - while (ch != -1) { - switch (ch) { - case ' ': - case '\t': - case '\f': - if (quoteChar == 0) { - return sb.toString(); - } - sb.append((char) ch); - break; - - case '\n': - case '\r': - return sb.toString(); - - case '\'': - case '"': - if (quoteChar == 0) { - quoteChar = (char) ch; - } else if (quoteChar == ch) { - quoteChar = 0; - } else { - sb.append((char) ch); - } - break; - - case '\\': - if (quoteChar != 0) { - ch = in.read(); - switch (ch) { - case '\n': - case '\r': - while (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f') { - ch = in.read(); - } - continue; - - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 't': - ch = '\t'; - break; - case 'f': - ch = '\f'; - break; - } - } - sb.append((char) ch); - break; - - default: - sb.append((char) ch); - } - - ch = in.read(); - } - - return sb.toString(); - } - - void skipWhite() throws IOException { - while (ch != -1) { - switch (ch) { - case ' ': - case '\t': - case '\n': - case '\r': - case '\f': - break; - - case '#': - ch = in.read(); - while (ch != '\n' && ch != '\r' && ch != -1) { - ch = in.read(); - } - break; - - default: - return; - } - - ch = in.read(); - } - } - } - - @SuppressWarnings("fallthrough") - private static void appendParsedEnvVariables(List newArgs, String envVariable) - throws UnmatchedQuote { - - if (envVariable == null) { - return; - } - String in = System.getenv(envVariable); - if (in == null || in.trim().isEmpty()) { - return; - } - - final char NUL = (char)0; - final int len = in.length(); - - int pos = 0; - StringBuilder sb = new StringBuilder(); - char quote = NUL; - char ch; - - loop: - while (pos < len) { - ch = in.charAt(pos); - switch (ch) { - case '\"': case '\'': - if (quote == NUL) { - quote = ch; - } else if (quote == ch) { - quote = NUL; - } else { - sb.append(ch); - } - pos++; - break; - case '\f': case '\n': case '\r': case '\t': case ' ': - if (quote == NUL) { - newArgs.add(sb.toString()); - sb.setLength(0); - while (ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - pos++; - if (pos >= len) { - break loop; - } - ch = in.charAt(pos); - } - break; - } - // fall through - default: - sb.append(ch); - pos++; - } - } - if (sb.length() != 0) { - newArgs.add(sb.toString()); - } - if (quote != NUL) { - throw new UnmatchedQuote(envVariable); - } - } - - public static class UnmatchedQuote extends Exception { - private static final long serialVersionUID = 0; - - public final String variableName; - - UnmatchedQuote(String variable) { - this.variableName = variable; - } - } -} diff --git a/make/langtools/tools/javacserver/options/Option.java b/make/langtools/tools/javacserver/options/Option.java deleted file mode 100644 index 2856c65627b..00000000000 --- a/make/langtools/tools/javacserver/options/Option.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.options; - -/** - * Sjavac options can be classified as: - * - * (1) relevant only for sjavac, such as --server - * (2) relevant for sjavac and javac, such as -d, or - * (3) relevant only for javac, such as -g. - * - * This enum represents all options from (1) and (2). Note that instances of - * this enum only entail static information about the option. For storage of - * option values, refer to Options. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public enum Option { - SERVER("--server:", "Specify server configuration file of running server") { - @Override - protected void processMatching(ArgumentIterator iter, Options.ArgDecoderOptionHelper helper) { - helper.serverConf(iter.current().substring(arg.length())); - } - }, - STARTSERVER("--startserver:", "Start server and use the given configuration file") { - @Override - protected void processMatching(ArgumentIterator iter, Options.ArgDecoderOptionHelper helper) { - helper.startServerConf(iter.current().substring(arg.length())); - } - }; - - - public final String arg; - - final String description; - - private Option(String arg, String description) { - this.arg = arg; - this.description = description; - } - - // Future cleanup: Change the "=" syntax to ":" syntax to be consistent and - // to follow the javac-option style. - - public boolean hasOption() { - return arg.endsWith(":") || arg.endsWith("="); - } - - - /** - * Process current argument of argIter. - * - * It's final, since the option customization is typically done in - * processMatching. - * - * @param argIter Iterator to read current and succeeding arguments from. - * @param helper The helper to report back to. - * @return true iff the argument was processed by this option. - */ - public final boolean processCurrent(ArgumentIterator argIter, - Options.ArgDecoderOptionHelper helper) { - String fullArg = argIter.current(); // "-tr" or "-log=level" - if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) { - processMatching(argIter, helper); - return true; - } - // Did not match - return false; - } - - /** Called by process if the current argument matches this option. */ - protected abstract void processMatching(ArgumentIterator argIter, - Options.ArgDecoderOptionHelper helper); -} diff --git a/make/langtools/tools/javacserver/options/Options.java b/make/langtools/tools/javacserver/options/Options.java deleted file mode 100644 index 507e7134fdd..00000000000 --- a/make/langtools/tools/javacserver/options/Options.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.options; - -import java.util.List; - -/** - * Instances of this class represent values for sjavac command line options. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Options { - private String logLevel = "info"; - - private boolean startServer = false; - - // Server configuration string - private String serverConf; - - /** Get the log level. */ - public String getLogLevel() { - return logLevel; - } - - /** Return true iff a new server should be started */ - public boolean startServerFlag() { - return startServer; - } - - /** Return the server configuration string. */ - public String getServerConf() { - return serverConf; - } - - /** - * Parses the given argument array and returns a corresponding Options - * instance. - */ - public static Options parseArgs(String... args) { - Options options = new Options(); - options.new ArgDecoderOptionHelper().traverse(args); - return options; - } - - // OptionHelper that records the traversed options in this Options instance. - public class ArgDecoderOptionHelper { - public void reportError(String msg) { - throw new IllegalArgumentException(msg); - } - - public void serverConf(String conf) { - if (serverConf != null) - reportError("Can not specify more than one server configuration."); - else - serverConf = conf; - } - - public void startServerConf(String conf) { - if (serverConf != null) - reportError("Can not specify more than one server configuration."); - else { - startServer = true; - serverConf = conf; - } - } - - /** - * Traverses an array of arguments and performs the appropriate callbacks. - * - * @param args the arguments to traverse. - */ - void traverse(String[] args) { - Iterable allArgs; - try { - allArgs = CommandLine.parse(List.of(args)); // Detect @file and load it as a command line. - } catch (java.io.IOException e) { - throw new IllegalArgumentException("Problem reading @"+e.getMessage()); - } - ArgumentIterator argIter = new ArgumentIterator(allArgs); - - nextArg: - while (argIter.hasNext()) { - - String arg = argIter.next(); - - if (arg.startsWith("-")) { - for (Option opt : Option.values()) { - if (opt.processCurrent(argIter, this)) - continue nextArg; - } - } - } - } - } -} diff --git a/make/langtools/tools/javacserver/comp/PooledSjavac.java b/make/langtools/tools/javacserver/server/CompilerThreadPool.java similarity index 60% rename from make/langtools/tools/javacserver/comp/PooledSjavac.java rename to make/langtools/tools/javacserver/server/CompilerThreadPool.java index 3647f17cc10..3f3dea52c84 100644 --- a/make/langtools/tools/javacserver/comp/PooledSjavac.java +++ b/make/langtools/tools/javacserver/server/CompilerThreadPool.java @@ -23,54 +23,38 @@ * questions. */ -package javacserver.comp; +package javacserver.server; -import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - -import javacserver.Log; -import javacserver.Result; -import javacserver.server.Sjavac; +import javacserver.util.Log; /** - * An sjavac implementation that limits the number of concurrent calls by - * wrapping invocations in Callables and delegating them to a FixedThreadPool. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Use a fixed thread pool to limit the amount of concurrent javac compilation + * that can happen. */ -public class PooledSjavac implements Sjavac { +public class CompilerThreadPool { + private static final int POOLSIZE = Runtime.getRuntime().availableProcessors(); - final Sjavac delegate; - final ExecutorService pool; + private final ExecutorService pool; - public PooledSjavac(Sjavac delegate, int poolsize) { - Objects.requireNonNull(delegate); - this.delegate = delegate; - pool = Executors.newFixedThreadPool(poolsize); + public CompilerThreadPool() { + this.pool = Executors.newFixedThreadPool(POOLSIZE); } - @Override - public Result compile(String[] args) { + public int dispatchCompilation(String[] args) { Log log = Log.get(); try { - return pool.submit(() -> { - Log.setLogForCurrentThread(log); - return delegate.compile(args); - }).get(); + return pool.submit(() -> Server.runCompiler(log, args)).get(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Error during compile", e); } } - @Override public void shutdown() { - Log.debug("Shutting down PooledSjavac"); + Log.debug("Shutting down javacserver thread pool"); pool.shutdown(); // Disable new tasks from being submitted try { // Wait a while for existing tasks to terminate @@ -78,16 +62,17 @@ public void shutdown() { pool.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(60, TimeUnit.SECONDS)) - Log.error("ThreadPool did not terminate"); + Log.error("Thread pool did not terminate"); } } catch (InterruptedException ie) { - // (Re-)Cancel if current thread also interrupted - pool.shutdownNow(); - // Preserve interrupt status - Thread.currentThread().interrupt(); + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); } - - delegate.shutdown(); } + public int poolSize() { + return POOLSIZE; + } } diff --git a/make/langtools/tools/javacserver/server/IdleResetSjavac.java b/make/langtools/tools/javacserver/server/IdleMonitor.java similarity index 59% rename from make/langtools/tools/javacserver/server/IdleResetSjavac.java rename to make/langtools/tools/javacserver/server/IdleMonitor.java index be4be86c622..939a97beebb 100644 --- a/make/langtools/tools/javacserver/server/IdleResetSjavac.java +++ b/make/langtools/tools/javacserver/server/IdleMonitor.java @@ -27,53 +27,30 @@ import java.util.Timer; import java.util.TimerTask; - -import javacserver.Log; -import javacserver.Result; +import java.util.function.Consumer; +import javacserver.util.RunnableTimerTask; /** - * An sjavac implementation that keeps track of idleness and shuts down the - * given Terminable upon idleness timeout. - * - * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last - * request is completed. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Monitors the javacserver daemon, shutting it down if it recieves no new requests + * after a certain amount of time. */ -public class IdleResetSjavac implements Sjavac { +public class IdleMonitor { + // Accept 120 seconds of inactivity before quitting. + private static final int KEEPALIVE = 120; - private final Sjavac delegate; - private final Terminable toShutdown; + private final Consumer onShutdown; private final Timer idlenessTimer = new Timer(); - private final long idleTimeout; private int outstandingCalls = 0; // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled private TimerTask idlenessTimerTask; - public IdleResetSjavac(Sjavac delegate, - Terminable toShutdown, - long idleTimeout) { - this.delegate = delegate; - this.toShutdown = toShutdown; - this.idleTimeout = idleTimeout; + public IdleMonitor(Consumer onShutdown) { + this.onShutdown = onShutdown; scheduleTimeout(); } - @Override - public Result compile(String[] args) { - startCall(); - try { - return delegate.compile(args); - } finally { - endCall(); - } - } - - private synchronized void startCall() { + public synchronized void startCall() { // Was there no outstanding calls before this call? if (++outstandingCalls == 1) { // Then the timer task must have been scheduled @@ -85,7 +62,7 @@ private synchronized void startCall() { } } - private synchronized void endCall() { + public synchronized void endCall() { if (--outstandingCalls == 0) { // No more outstanding calls. Schedule timeout. scheduleTimeout(); @@ -95,19 +72,14 @@ private synchronized void endCall() { private void scheduleTimeout() { if (idlenessTimerTask != null) throw new IllegalStateException("Idle timeout already scheduled"); - idlenessTimerTask = new TimerTask() { - public void run() { - Log.setLogForCurrentThread(ServerMain.getErrorLog()); - toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); - } - }; - idlenessTimer.schedule(idlenessTimerTask, idleTimeout); + idlenessTimerTask = new RunnableTimerTask(() -> { + Server.restoreServerErrorLog(); + onShutdown.accept("Server has been idle for " + KEEPALIVE + " seconds."); + }); + idlenessTimer.schedule(idlenessTimerTask, KEEPALIVE * 1000); } - @Override public void shutdown() { idlenessTimer.cancel(); - delegate.shutdown(); } - } diff --git a/make/langtools/tools/javacserver/server/PortFileMonitor.java b/make/langtools/tools/javacserver/server/PortFileMonitor.java index 1b8828c694b..41a357b6db5 100644 --- a/make/langtools/tools/javacserver/server/PortFileMonitor.java +++ b/make/langtools/tools/javacserver/server/PortFileMonitor.java @@ -27,68 +27,61 @@ import java.io.IOException; import java.util.Timer; -import java.util.TimerTask; - -import javacserver.Log; +import java.util.function.Consumer; +import javacserver.shared.PortFile; +import javacserver.util.Log; +import javacserver.util.RunnableTimerTask; /** - * Monitors the presence of a port file and shuts down the given SjavacServer + * Monitors the presence of a port file and shuts down the server * whenever the port file is deleted or invalidated. * * TODO: JDK-8046882 - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. */ public class PortFileMonitor { - // Check if the portfile is gone, every 5 seconds. private static final int CHECK_PORTFILE_INTERVAL = 5000; private final Timer timer = new Timer(); private final PortFile portFile; - private final SjavacServer server; + private final Consumer onShutdown; public PortFileMonitor(PortFile portFile, - SjavacServer server) { + Consumer onShutdown) { this.portFile = portFile; - this.server = server; + this.onShutdown = onShutdown; } public void start() { Log log = Log.get(); - TimerTask shutdownCheck = new TimerTask() { - public void run() { - Log.setLogForCurrentThread(log); - Log.debug("Checking port file status..."); - try { - if (!portFile.exists()) { - // Time to quit because the portfile was deleted by another - // process, probably by the makefile that is done building. - server.shutdown("Quitting because portfile was deleted!"); - } else if (portFile.markedForStop()) { - // Time to quit because another process touched the file - // server.port.stop to signal that the server should stop. - // This is necessary on some operating systems that lock - // the port file hard! - server.shutdown("Quitting because a portfile.stop file was found!"); - } else if (!portFile.stillMyValues()) { - // Time to quit because another build has started. - server.shutdown("Quitting because portfile is now owned by another javac server!"); - } - } catch (IOException e) { - Log.error("IOException caught in PortFileMonitor."); - Log.debug(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - Log.error(e); - } - } - }; + timer.schedule(new RunnableTimerTask(() -> checkPortFile(log)), 0, CHECK_PORTFILE_INTERVAL); + } - timer.schedule(shutdownCheck, 0, CHECK_PORTFILE_INTERVAL); + private void checkPortFile(Log log) { + Log.setLogForCurrentThread(log); + Log.debug("Checking port file status..."); + try { + if (!portFile.exists()) { + // Time to quit because the portfile was deleted by another + // process, probably by the makefile that is done building. + onShutdown.accept("Quitting because portfile was deleted!"); + } else if (portFile.markedForStop()) { + // Time to quit because another process touched the file + // server.port.stop to signal that the server should stop. + // This is necessary on some operating systems that lock + // the port file hard! + onShutdown.accept("Quitting because a portfile.stop file was found!"); + } else if (!portFile.stillMyValues()) { + // Time to quit because another build has started. + onShutdown.accept("Quitting because portfile is now owned by another javac server!"); + } + } catch (IOException e) { + Log.error("IOException caught in PortFileMonitor."); + Log.debug(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + Log.error(e); + } } public void shutdown() { diff --git a/make/langtools/tools/javacserver/server/RequestHandler.java b/make/langtools/tools/javacserver/server/RequestHandler.java deleted file mode 100644 index b2d04e4606b..00000000000 --- a/make/langtools/tools/javacserver/server/RequestHandler.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.server; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.net.Socket; -import java.nio.file.Path; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; - -import static javacserver.server.SjavacServer.LINE_TYPE_RC; - - -/** - * A RequestHandler handles requests performed over a socket. Specifically it - * - Reads the command string specifying which method is to be invoked - * - Reads the appropriate arguments - * - Delegates the actual invocation to the given sjavac implementation - * - Writes the result back to the socket output stream - * - * None of the work performed by this class is really bound by the CPU. It - * should be completely fine to have a large number of RequestHandlers active. - * To limit the number of concurrent compilations, use PooledSjavac. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RequestHandler extends Thread { - - private final Socket socket; - private final Sjavac sjavac; - - public RequestHandler(Socket socket, Sjavac sjavac) { - this.socket = socket; - this.sjavac = sjavac; - } - - @Override - public void run() { - - try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { - - // Set up logging for this thread. Stream back logging messages to - // client on the format format "level:msg". - Log.setLogForCurrentThread(new Log(out, out) { - @Override - protected boolean isLevelLogged(Level l) { - // Make sure it is up to the client to decide whether or - // not this message should be displayed. - return true; - } - - @Override - protected void printLogMsg(Level msgLevel, String msg) { - // Follow sjavac server/client protocol: Send one line - // at a time and prefix with message with "level:". - Util.getLines(msg) - .map(line -> msgLevel + ":" + line) - .forEach(line -> super.printLogMsg(msgLevel, line)); - } - }); - - // Read argument array - int n = Integer.parseInt(in.readLine()); - String[] args = new String[n]; - for (int i = 0; i < n; i++) { - args[i] = in.readLine(); - } - - // If there has been any internal errors, notify client - checkInternalErrorLog(); - - // Perform compilation - Result rc = sjavac.compile(args); - - // Send return code back to client - out.println(LINE_TYPE_RC + ":" + rc.name()); - - // Check for internal errors again. - checkInternalErrorLog(); - } catch (Exception ex) { - // Not much to be done at this point. The client side request - // code will most likely throw an IOException and the - // compilation will fail. - Log.error(ex); - } finally { - Log.setLogForCurrentThread(null); - } - } - - private void checkInternalErrorLog() { - Path errorLog = ServerMain.getErrorLog().getLogDestination(); - if (errorLog != null) { - Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath() - + " for details."); - } - } -} diff --git a/make/langtools/tools/javacserver/server/Server.java b/make/langtools/tools/javacserver/server/Server.java new file mode 100644 index 00000000000..b213c992667 --- /dev/null +++ b/make/langtools/tools/javacserver/server/Server.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2011, 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. 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 javacserver.server; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.nio.file.Path; +import java.util.Optional; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.spi.ToolProvider; +import javacserver.shared.PortFile; +import javacserver.shared.Protocol; +import javacserver.shared.Result; +import javacserver.util.LazyInitFileLog; +import javacserver.util.Log; +import javacserver.util.LoggingOutputStream; +import javacserver.util.Util; + +/** + * Start a new server main thread, that will listen to incoming connection requests from the client, + * and dispatch these on to worker threads in a thread pool, running javac. + */ +public class Server { + private ServerSocket serverSocket; + private PortFile portFile; + private PortFileMonitor portFileMonitor; + private IdleMonitor idleMonitor; + private CompilerThreadPool compilerThreadPool; + + // Set to false break accept loop + final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); + + // For logging server internal (non request specific) errors. + private static LazyInitFileLog errorLog; + + public static void main(String... args) { + initLogging(); + + try { + PortFile portFile = getPortFileFromArguments(args); + if (portFile == null) { + System.exit(Result.CMDERR.exitCode); + return; + } + + Server server = new Server(portFile); + if (!server.start()) { + System.exit(Result.ERROR.exitCode); + } else { + System.exit(Result.OK.exitCode); + } + } catch (IOException | InterruptedException ex) { + ex.printStackTrace(); + System.exit(Result.ERROR.exitCode); + } + } + + private static void initLogging() { + // Under normal operation, all logging messages generated server-side + // are due to compilation requests. These logging messages should + // be relayed back to the requesting client rather than written to the + // server log. The only messages that should be written to the server + // log (in production mode) should be errors, + errorLog = new LazyInitFileLog("server.log"); + Log.setLogForCurrentThread(errorLog); + Log.setLogLevel(Log.Level.ERROR); // should be set to ERROR. + + // Make sure no exceptions go under the radar + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + restoreServerErrorLog(); + Log.error(e); + }); + + // Inevitably someone will try to print messages using System.{out,err}. + // Make sure this output also ends up in the log. + System.setOut(new PrintStream(new LoggingOutputStream(System.out, Log.Level.INFO, "[stdout] "))); + System.setErr(new PrintStream(new LoggingOutputStream(System.err, Log.Level.ERROR, "[stderr] "))); + } + + private static PortFile getPortFileFromArguments(String[] args) { + if (args.length != 1) { + Log.error("javacserver daemon incorrectly called"); + return null; + } + String portfilename = args[0]; + PortFile portFile = new PortFile(portfilename); + return portFile; + } + + public Server(PortFile portFile) throws FileNotFoundException { + this.portFile = portFile; + } + + /** + * Start the daemon, unless another one is already running, in which it returns + * false and exits immediately. + */ + private boolean start() throws IOException, InterruptedException { + // The port file is locked and the server port and cookie is written into it. + portFile.lock(); + portFile.getValues(); + if (portFile.containsPortInfo()) { + Log.debug("javacserver daemon not started because portfile exists!"); + portFile.unlock(); + return false; + } + + serverSocket = new ServerSocket(); + InetAddress localhost = InetAddress.getByName(null); + serverSocket.bind(new InetSocketAddress(localhost, 0)); + + // At this point the server accepts connections, so it is now safe + // to publish the port / cookie information + + // The secret cookie shared between server and client through the port file. + // Used to prevent clients from believing that they are communicating with + // an old server when a new server has started and reused the same port as + // an old server. + long myCookie = new Random().nextLong(); + portFile.setValues(serverSocket.getLocalPort(), myCookie); + portFile.unlock(); + + portFileMonitor = new PortFileMonitor(portFile, this::shutdownServer); + portFileMonitor.start(); + compilerThreadPool = new CompilerThreadPool(); + idleMonitor = new IdleMonitor(this::shutdownServer); + + Log.debug("javacserver daemon started. Accepting connections..."); + Log.debug(" port: " + serverSocket.getLocalPort()); + Log.debug(" time: " + new java.util.Date()); + Log.debug(" poolsize: " + compilerThreadPool.poolSize()); + + keepAcceptingRequests.set(true); + do { + try { + Socket socket = serverSocket.accept(); + // Handle each incoming request in a separate thread. This is just for socket communication, + // the actual compilation will be done by the threadpool. + Thread requestHandler = new Thread(() -> handleRequest(socket)); + requestHandler.start(); + } catch (SocketException se) { + // Caused by serverSocket.close() and indicates shutdown + } + } while (keepAcceptingRequests.get()); + + Log.debug("Shutting down."); + + // No more connections accepted. If any client managed to connect after + // the accept() was interrupted but before the server socket is closed + // here, any attempt to read or write to the socket will result in an + // IOException on the client side. + + // Shut down + idleMonitor.shutdown(); + compilerThreadPool.shutdown(); + + return true; + } + + private void handleRequest(Socket socket) { + try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { + try { + idleMonitor.startCall(); + + // Set up logging for this thread. Stream back logging messages to + // client on the format "level:msg". + Log.setLogForCurrentThread(new Protocol.ProtocolLog(out)); + + String[] args = Protocol.readCommand(in); + + // If there has been any internal errors, notify client + checkInternalErrorLog(); + + // Perform compilation. This will call runCompiler() on a + // thread in the thread pool + int exitCode = compilerThreadPool.dispatchCompilation(args); + Protocol.sendExitCode(out, exitCode); + + // Check for internal errors again. + checkInternalErrorLog(); + } finally { + idleMonitor.endCall(); + } + } catch (Exception ex) { + // Not much to be done at this point. The client side request + // code will most likely throw an IOException and the + // compilation will fail. + Log.error(ex); + } finally { + Log.setLogForCurrentThread(null); + } + } + + public static int runCompiler(Log log, String[] args) { + Log.setLogForCurrentThread(log); + + // Direct logging to our byte array stream. + StringWriter strWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(strWriter); + + // Compile + Optional tool = ToolProvider.findFirst("javac"); + if (tool.isEmpty()) { + Log.error("Can't find tool javac"); + return Result.ERROR.exitCode; + } + int exitcode = tool.get().run(printWriter, printWriter, args); + + // Process compiler output (which is always errors) + printWriter.flush(); + Util.getLines(strWriter.toString()).forEach(Log::error); + + return exitcode; + } + + private void checkInternalErrorLog() { + Path errorLogPath = errorLog.getLogDestination(); + if (errorLogPath != null) { + Log.error("Server has encountered an internal error. See " + errorLogPath.toAbsolutePath() + + " for details."); + } + } + + public static void restoreServerErrorLog() { + Log.setLogForCurrentThread(errorLog); + } + + public void shutdownServer(String quitMsg) { + if (!keepAcceptingRequests.compareAndSet(true, false)) { + // Already stopped, no need to shut down again + return; + } + + Log.debug("Quitting: " + quitMsg); + + portFileMonitor.shutdown(); // No longer any need to monitor port file + + // Unpublish port before shutting down socket to minimize the number of + // failed connection attempts + try { + portFile.delete(); + } catch (IOException | InterruptedException e) { + Log.error(e); + } + try { + serverSocket.close(); + } catch (IOException e) { + Log.error(e); + } + } +} diff --git a/make/langtools/tools/javacserver/server/ServerMain.java b/make/langtools/tools/javacserver/server/ServerMain.java deleted file mode 100644 index 1f5b51755bb..00000000000 --- a/make/langtools/tools/javacserver/server/ServerMain.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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. 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 javacserver.server; - -import java.io.IOException; -import java.io.PrintStream; - -import javacserver.Log; -import javacserver.Result; -import javacserver.server.log.LazyInitFileLog; -import javacserver.server.log.LoggingOutputStream; - -import static javacserver.Log.Level.ERROR; -import static javacserver.Log.Level.INFO; - -/** - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ServerMain { - - // For logging server internal (non request specific) errors. - private static LazyInitFileLog errorLog; - - public static int run(String[] args) { - - // Under normal operation, all logging messages generated server-side - // are due to compilation requests. These logging messages should - // be relayed back to the requesting client rather than written to the - // server log. The only messages that should be written to the server - // log (in production mode) should be errors, - Log.setLogForCurrentThread(errorLog = new LazyInitFileLog("server.log")); - Log.setLogLevel(ERROR); // should be set to ERROR. - - // Make sure no exceptions go under the radar - Thread.setDefaultUncaughtExceptionHandler((t, e) -> { - Log.setLogForCurrentThread(errorLog); - Log.error(e); - }); - - // Inevitably someone will try to print messages using System.{out,err}. - // Make sure this output also ends up in the log. - System.setOut(new PrintStream(new LoggingOutputStream(System.out, INFO, "[stdout] "))); - System.setErr(new PrintStream(new LoggingOutputStream(System.err, ERROR, "[stderr] "))); - - // Any options other than --startserver? - if (args.length > 1) { - Log.error("When spawning a background server, only a single --startserver argument is allowed."); - return Result.CMDERR.exitCode; - } - - int exitCode; - try { - SjavacServer server = new SjavacServer(args[0]); - exitCode = server.startServer(); - } catch (IOException | InterruptedException ex) { - ex.printStackTrace(); - exitCode = Result.ERROR.exitCode; - } - - return exitCode; - } - - public static LazyInitFileLog getErrorLog() { - return errorLog; - } -} diff --git a/make/langtools/tools/javacserver/server/SjavacServer.java b/make/langtools/tools/javacserver/server/SjavacServer.java deleted file mode 100644 index d52e274c4ac..00000000000 --- a/make/langtools/tools/javacserver/server/SjavacServer.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2011, 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. 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 javacserver.server; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.comp.PooledSjavac; -import javacserver.comp.SjavacImpl; - -/** - * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacServer implements Terminable { - - // Prefix of line containing return code. - public static final String LINE_TYPE_RC = "RC"; - - private final String portfilename; - private final int poolsize; - private final int keepalive; - - // The secret cookie shared between server and client through the port file. - // Used to prevent clients from believing that they are communicating with - // an old server when a new server has started and reused the same port as - // an old server. - private final long myCookie; - - // Accumulated build time, not counting idle time, used for logging purposes - private long totalBuildTime; - - // The sjavac implementation to delegate requests to - Sjavac sjavac; - - private ServerSocket serverSocket; - - private PortFile portFile; - private PortFileMonitor portFileMonitor; - - // Set to false break accept loop - final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); - - // For the client, all port files fetched, one per started javac server. - // Though usually only one javac server is started by a client. - private static Map allPortFiles; - - public SjavacServer(String settings) throws FileNotFoundException { - this(Util.extractStringOption("portfile", settings), - Util.extractIntOption("poolsize", settings, Runtime.getRuntime().availableProcessors()), - Util.extractIntOption("keepalive", settings, 120)); - } - - public SjavacServer(String portfilename, - int poolsize, - int keepalive) - throws FileNotFoundException { - this.portfilename = portfilename; - this.poolsize = poolsize; - this.keepalive = keepalive; - this.myCookie = new Random().nextLong(); - } - - - /** - * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. - */ - public static synchronized PortFile getPortFile(String filename) { - if (allPortFiles == null) { - allPortFiles = new HashMap<>(); - } - PortFile pf = allPortFiles.get(filename); - - // Port file known. Does it still exist? - if (pf != null) { - try { - if (!pf.exists()) - pf = null; - } catch (IOException ioex) { - ioex.printStackTrace(); - } - } - - if (pf == null) { - pf = new PortFile(filename); - allPortFiles.put(filename, pf); - } - return pf; - } - - /** - * Get the cookie used for this server. - */ - long getCookie() { - return myCookie; - } - - /** - * Get the port used for this server. - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Sum up the total build time for this javac server. - */ - public void addBuildTime(long inc) { - totalBuildTime += inc; - } - - /** - * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" - * is sent as the settings parameter. Returns 0 on success, -1 on failure. - */ - public int startServer() throws IOException, InterruptedException { - long serverStart = System.currentTimeMillis(); - - // The port file is locked and the server port and cookie is written into it. - portFile = getPortFile(portfilename); - - synchronized (portFile) { - portFile.lock(); - portFile.getValues(); - if (portFile.containsPortInfo()) { - Log.debug("Javac server not started because portfile exists!"); - portFile.unlock(); - return Result.ERROR.exitCode; - } - - // .-----------. .--------. .------. - // socket -->| IdleReset |-->| Pooled |-->| Impl |--> javac - // '-----------' '--------' '------' - sjavac = new SjavacImpl(); - sjavac = new PooledSjavac(sjavac, poolsize); - sjavac = new IdleResetSjavac(sjavac, - this, - keepalive * 1000); - - serverSocket = new ServerSocket(); - InetAddress localhost = InetAddress.getByName(null); - serverSocket.bind(new InetSocketAddress(localhost, 0)); - - // At this point the server accepts connections, so it is now safe - // to publish the port / cookie information - portFile.setValues(getPort(), getCookie()); - portFile.unlock(); - } - - portFileMonitor = new PortFileMonitor(portFile, this); - portFileMonitor.start(); - - Log.debug("Sjavac server started. Accepting connections..."); - Log.debug(" port: " + getPort()); - Log.debug(" time: " + new java.util.Date()); - Log.debug(" poolsize: " + poolsize); - - - keepAcceptingRequests.set(true); - do { - try { - Socket socket = serverSocket.accept(); - new RequestHandler(socket, sjavac).start(); - } catch (SocketException se) { - // Caused by serverSocket.close() and indicates shutdown - } - } while (keepAcceptingRequests.get()); - - Log.debug("Shutting down."); - - // No more connections accepted. If any client managed to connect after - // the accept() was interrupted but before the server socket is closed - // here, any attempt to read or write to the socket will result in an - // IOException on the client side. - - long realTime = System.currentTimeMillis() - serverStart; - Log.debug("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - - // Shut down - sjavac.shutdown(); - - return Result.OK.exitCode; - } - - @Override - public void shutdown(String quitMsg) { - if (!keepAcceptingRequests.compareAndSet(true, false)) { - // Already stopped, no need to shut down again - return; - } - - Log.debug("Quitting: " + quitMsg); - - portFileMonitor.shutdown(); // No longer any need to monitor port file - - // Unpublish port before shutting down socket to minimize the number of - // failed connection attempts - try { - portFile.delete(); - } catch (IOException | InterruptedException e) { - Log.error(e); - } - try { - serverSocket.close(); - } catch (IOException e) { - Log.error(e); - } - } -} diff --git a/make/langtools/tools/javacserver/server/PortFile.java b/make/langtools/tools/javacserver/shared/PortFile.java similarity index 94% rename from make/langtools/tools/javacserver/server/PortFile.java rename to make/langtools/tools/javacserver/shared/PortFile.java index 3874a4c1ee2..2e4283a22b3 100644 --- a/make/langtools/tools/javacserver/server/PortFile.java +++ b/make/langtools/tools/javacserver/shared/PortFile.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.server; +package javacserver.shared; import java.io.File; import java.io.FileNotFoundException; @@ -34,23 +34,15 @@ import java.nio.channels.FileLock; import java.nio.channels.FileLockInterruptionException; import java.util.concurrent.Semaphore; - -import javacserver.Log; -import javacserver.client.PortFileInaccessibleException; +import javacserver.util.Log; /** * The PortFile class mediates access to a short binary file containing the tcp/ip port (for the localhost) * and a cookie necessary for the server answering on that port. The file can be locked using file system * primitives to avoid race conditions when several javac clients are started at the same. Note that file - * system locking is not always supported on a all operating systems and/or file systems. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * system locking is not always supported on all operating systems and/or file systems. */ public class PortFile { - // Port file format: // byte ordering: high byte first = big endian // Magic nr, 4 byte int, first in file. @@ -225,6 +217,19 @@ public void unlock() throws IOException { lockSem.release(); } + public boolean hasValidValues() throws IOException, InterruptedException { + if (exists()) { + lock(); + getValues(); + unlock(); + + if (containsPortInfo()) { + return true; + } + } + return false; + } + /** * Wait for the port file to contain values that look valid. */ @@ -277,7 +282,7 @@ public boolean stillMyValues() throws IOException, FileNotFoundException, Interr continue; } catch (ClosedChannelException e) { - // The channel has been closed since sjavac is exiting. + // The channel has been closed since the server is exiting. return false; } } diff --git a/make/langtools/tools/javacserver/client/PortFileInaccessibleException.java b/make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java similarity index 98% rename from make/langtools/tools/javacserver/client/PortFileInaccessibleException.java rename to make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java index c9db8dfc44a..b306893c20d 100644 --- a/make/langtools/tools/javacserver/client/PortFileInaccessibleException.java +++ b/make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.client; +package javacserver.shared; import java.io.IOException; diff --git a/make/langtools/tools/javacserver/shared/Protocol.java b/make/langtools/tools/javacserver/shared/Protocol.java new file mode 100644 index 00000000000..f4f0f23cdc6 --- /dev/null +++ b/make/langtools/tools/javacserver/shared/Protocol.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014, 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. 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 javacserver.shared; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import javacserver.util.Log; +import javacserver.util.Util; + +/** + * Implementation of the wire protocol used by the javacserver client and daemon to communicate. + * Basically, the client sends the argument to javac, one line per string. The server responds + * with log lines (if there is any output), and the exit code from javac. + */ +public class Protocol { + // Prefix of line containing return code. + private static final String LINE_TYPE_RC = "RC"; + + public static void sendCommand(PrintWriter out, String[] args) throws IOException { + // Send args array to server + out.println(args.length); + for (String arg : args) + out.println(arg); + out.flush(); + } + + public static String[] readCommand(BufferedReader in) throws IOException { + // Read argument array + int n = Integer.parseInt(in.readLine()); + String[] args = new String[n]; + for (int i = 0; i < n; i++) { + args[i] = in.readLine(); + } + return args; + } + + public static void sendExitCode(PrintWriter out, int exitCode) { + // Send return code back to client + out.println(LINE_TYPE_RC + ":" + exitCode); + } + + public static int readResponse(BufferedReader in) throws IOException { + // Read server response line by line + String line; + while (null != (line = in.readLine())) { + Line parsedLine = new Line(line); + + try { + String content = parsedLine.getContent(); + if (Log.isDebugging()) { + // Distinguish server generated output if debugging. + content = "[javacserver] " + content; + } + Log.log(Log.Level.valueOf(parsedLine.getType()), content); + continue; + } catch (IllegalArgumentException e) { + // Parsing of 'type' as log level failed. + } + + if (parsedLine.isExitCode()) { + return parsedLine.getExitCode(); + } + } + // No exit code was found. + return Result.ERROR.exitCode; + } + + public static class Line { + private final String type; + + public String getType() { + return type; + } + + public String getContent() { + return content; + } + + public boolean isExitCode() { + return type.equals(LINE_TYPE_RC); + } + + public int getExitCode() { + return Integer.parseInt(content); + } + + private final String content; + + public Line(String line) { + if (!line.contains(":")) { + throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); + } + String[] typeAndContent = line.split(":", 2); + type = typeAndContent[0]; + content = typeAndContent[1]; + } + } + + public static class ProtocolLog extends Log { + public ProtocolLog(PrintWriter out) { + super(out, out); + } + + @Override + protected boolean isLevelLogged(Level l) { + // Make sure it is up to the client to decide whether or + // not this message should be displayed. + return true; + } + + @Override + protected void printLogMsg(Level msgLevel, String msg) { + // Follow the server/client protocol: Send one line + // at a time and prefix with message with "level:". + Util.getLines(msg) + .map(line -> msgLevel + ":" + line) + .forEach(line -> super.printLogMsg(msgLevel, line)); + } + } +} diff --git a/make/langtools/tools/javacserver/server/Terminable.java b/make/langtools/tools/javacserver/shared/Result.java similarity index 74% rename from make/langtools/tools/javacserver/server/Terminable.java rename to make/langtools/tools/javacserver/shared/Result.java index 5c598ddc420..f15c3dd3765 100644 --- a/make/langtools/tools/javacserver/server/Terminable.java +++ b/make/langtools/tools/javacserver/shared/Result.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -23,14 +23,19 @@ * questions. */ -package javacserver.server; +package javacserver.shared; /** - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Result codes. */ -public interface Terminable { - void shutdown(String quitMsg); +public enum Result { + OK(0), // Compilation completed with no errors. + ERROR(1), // Completed but reported errors. + CMDERR(2); // Bad command-line arguments + + public final int exitCode; + + Result(int exitCode) { + this.exitCode = exitCode; + } } diff --git a/make/langtools/tools/javacserver/AutoFlushWriter.java b/make/langtools/tools/javacserver/util/AutoFlushWriter.java similarity index 98% rename from make/langtools/tools/javacserver/AutoFlushWriter.java rename to make/langtools/tools/javacserver/util/AutoFlushWriter.java index 92d64399690..1c06d558a8c 100644 --- a/make/langtools/tools/javacserver/AutoFlushWriter.java +++ b/make/langtools/tools/javacserver/util/AutoFlushWriter.java @@ -23,14 +23,13 @@ * questions. */ -package javacserver; +package javacserver.util; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; public class AutoFlushWriter extends FilterWriter { - public AutoFlushWriter(Writer out) { super(out); } diff --git a/make/langtools/tools/javacserver/server/log/LazyInitFileLog.java b/make/langtools/tools/javacserver/util/LazyInitFileLog.java similarity index 97% rename from make/langtools/tools/javacserver/server/log/LazyInitFileLog.java rename to make/langtools/tools/javacserver/util/LazyInitFileLog.java index 5471b8f0196..4de83b63176 100644 --- a/make/langtools/tools/javacserver/server/log/LazyInitFileLog.java +++ b/make/langtools/tools/javacserver/util/LazyInitFileLog.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.server.log; +package javacserver.util; import java.io.FileWriter; import java.io.IOException; @@ -32,10 +32,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -import javacserver.Log; - public class LazyInitFileLog extends Log { - String baseFilename; Path destination = null; diff --git a/make/langtools/tools/javacserver/Log.java b/make/langtools/tools/javacserver/util/Log.java similarity index 78% rename from make/langtools/tools/javacserver/Log.java rename to make/langtools/tools/javacserver/util/Log.java index 49b62876083..0c9d51e3c86 100644 --- a/make/langtools/tools/javacserver/Log.java +++ b/make/langtools/tools/javacserver/util/Log.java @@ -23,17 +23,16 @@ * questions. */ -package javacserver; +package javacserver.util; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.util.Locale; /** - * Utility class only for sjavac logging. + * Utility class only for javacserver logging. * - * Logging in sjavac has special requirements when running in server/client + * Logging in javacserver has special requirements when running in server/client * mode. Most of the log messages is generated server-side, but the server * is typically spawned by the client in the background, so the user usually * does not see the server stdout/stderr. For this reason log messages needs @@ -42,16 +41,9 @@ * instance so that each connected client can have its own instance that * relays messages back to the requesting client. * - * On the client-side (or when running sjavac without server-mode) there will - * typically just be one Log instance. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * On the client-side there will typically just be one Log instance. */ public class Log { - public enum Level { ERROR, WARN, @@ -61,7 +53,7 @@ public enum Level { } private static Log stdOutErr = new Log(new PrintWriter(System.out), new PrintWriter(System.err)); - private static ThreadLocal loggers = new ThreadLocal<>(); + private static ThreadLocal logger = new ThreadLocal<>(); protected PrintWriter err; // Used for error and warning messages protected PrintWriter out; // Used for other messages @@ -73,31 +65,19 @@ public Log(Writer out, Writer err) { } public static void setLogForCurrentThread(Log log) { - loggers.set(log); - } - - public static void setLogLevel(String l) { - setLogLevel(Level.valueOf(l.toUpperCase(Locale.US))); + logger.set(log); } public static void setLogLevel(Level l) { get().level = l; } - public static void trace(String msg) { - log(Level.TRACE, msg); - } - public static void debug(String msg) { log(Level.DEBUG, msg); } - public static void info(String msg) { - log(Level.INFO, msg); - } - - public static void warn(String msg) { - log(Level.WARN, msg); + public static void debug(Throwable t) { + log(Level.DEBUG, t); } public static void error(String msg) { @@ -112,10 +92,6 @@ public static void log(Level l, String msg) { get().printLogMsg(l, msg); } - public static void debug(Throwable t) { - log(Level.DEBUG, t); - } - public static void log(Level l, Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw, true)); @@ -131,7 +107,7 @@ protected boolean isLevelLogged(Level l) { } public static Log get() { - Log log = loggers.get(); + Log log = logger.get(); return log != null ? log : stdOutErr; } diff --git a/make/langtools/tools/javacserver/server/log/LoggingOutputStream.java b/make/langtools/tools/javacserver/util/LoggingOutputStream.java similarity index 97% rename from make/langtools/tools/javacserver/server/log/LoggingOutputStream.java rename to make/langtools/tools/javacserver/util/LoggingOutputStream.java index 6df616bd5e2..3b3f88d7647 100644 --- a/make/langtools/tools/javacserver/server/log/LoggingOutputStream.java +++ b/make/langtools/tools/javacserver/util/LoggingOutputStream.java @@ -23,17 +23,14 @@ * questions. */ -package javacserver.server.log; +package javacserver.util; import java.io.ByteArrayOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; -import javacserver.Log; - public class LoggingOutputStream extends FilterOutputStream { - private static final byte[] LINE_SEP = System.lineSeparator().getBytes(); private final Log.Level level; diff --git a/src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java b/make/langtools/tools/javacserver/util/RunnableTimerTask.java similarity index 68% rename from src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java rename to make/langtools/tools/javacserver/util/RunnableTimerTask.java index f6e3ea9465e..7d8f5aa3a43 100644 --- a/src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java +++ b/make/langtools/tools/javacserver/util/RunnableTimerTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -22,24 +22,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package sun.net; -import java.net.URL; +package javacserver.util; + +import java.util.TimerTask; /** - * ProgressMeteringPolicy is an interface for determining progress metering policy. - * - * @author Stanley Man-Kit Ho + * Wrapper class since TimerTask is not up to modern standards */ -public interface ProgressMeteringPolicy -{ - /** - * Return true if metering should be turned on for a particular network input stream. - */ - public boolean shouldMeterInput(URL url, String method); +public class RunnableTimerTask extends TimerTask { + private final Runnable task; + + public RunnableTimerTask(Runnable task) { + this.task = task; + } - /** - * Return update notification threshold. - */ - public int getProgressUpdateThreshold(); + @Override + public void run() { + task.run(); + } } diff --git a/make/langtools/tools/javacserver/server/Sjavac.java b/make/langtools/tools/javacserver/util/Util.java similarity index 72% rename from make/langtools/tools/javacserver/server/Sjavac.java rename to make/langtools/tools/javacserver/util/Util.java index 9c7c980c2f2..8381b1c3c6d 100644 --- a/make/langtools/tools/javacserver/server/Sjavac.java +++ b/make/langtools/tools/javacserver/util/Util.java @@ -23,20 +23,18 @@ * questions. */ -package javacserver.server; +package javacserver.util; -import javacserver.Result; +import java.util.regex.Pattern; +import java.util.stream.Stream; -/** - * Interface of the SjavacImpl, the sjavac client and all wrappers such as - * PooledSjavac etc. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public interface Sjavac { - Result compile(String[] args); - void shutdown(); +public class Util { + /** + * Return a stream of strings, where the input string is split at line separators. + */ + public static Stream getLines(String str) { + return str.isEmpty() + ? Stream.empty() + : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); + } } diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index e32277d4a42..fecd7a957bc 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -120,11 +120,6 @@ ifeq ($(call isTargetOs, windows), true) LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc endif -ifeq ($(call isTargetOs, linux), true) - # FIXME: This is probably not what we want to do, but keep it now for compatibility. - LIBAWT_CFLAGS += $(EXPORT_ALL_SYMBOLS) -endif - # Turn off all warnings for debug_mem.c This is needed because the specific warning # about initializing a declared 'extern' cannot be turned off individually. Only # applies to debug builds. This limitation in gcc is tracked in @@ -414,7 +409,7 @@ ifeq ($(FREETYPE_TO_USE), system) LIBFREETYPE_LIBS := $(FREETYPE_LIBS) else BUILD_LIBFREETYPE_HEADER_DIRS := $(TOPDIR)/src/$(MODULE)/share/native/libfreetype/include - BUILD_LIBFREETYPE_CFLAGS := -DFT2_BUILD_LIBRARY $(EXPORT_ALL_SYMBOLS) + BUILD_LIBFREETYPE_CFLAGS := -DFT2_BUILD_LIBRARY # For use by libfontmanager: LIBFREETYPE_CFLAGS := -I$(BUILD_LIBFREETYPE_HEADER_DIRS) diff --git a/make/modules/jdk.sctp/Java.gmk b/make/modules/jdk.sctp/Java.gmk index 05e27e1eaf8..10793d45c84 100644 --- a/make/modules/jdk.sctp/Java.gmk +++ b/make/modules/jdk.sctp/Java.gmk @@ -44,3 +44,10 @@ endif ifeq ($(call isTargetOs, aix), true) EXCLUDE_FILES += $(SCTP_IMPL_CLASSES) endif + +ifeq ($(call isTargetOsType, unix), true) + ifeq ($(call isTargetOs, macosx aix), false) + # This class is not needed on "unix" because SCTP in Java is supported for that platform + EXCLUDE_FILES += $(TOPDIR)/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java + endif +endif diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index 712487ce32b..6b89d02ad2f 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2018, 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. 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 build.tools.jfr; import java.io.BufferedOutputStream; @@ -573,9 +598,13 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro out.write("#include \"jfrfiles/jfrEventIds.hpp\""); out.write("#include \"memory/allocation.hpp\""); out.write(""); + out.write("enum PeriodicType {BEGIN_CHUNK, INTERVAL, END_CHUNK};"); + out.write(""); out.write("class JfrPeriodicEventSet : public AllStatic {"); out.write(" public:"); - out.write(" static void requestEvent(JfrEventId id) {"); + out.write(" static void requestEvent(JfrEventId id, jlong timestamp, PeriodicType periodicType) {"); + out.write(" _timestamp = Ticks(timestamp);"); + out.write(" _type = periodicType;"); out.write(" switch(id) {"); out.write(" "); for (TypeElement e : metadata.getPeriodicEvents()) { @@ -595,6 +624,10 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro out.write(" static void request" + e.name + "(void);"); out.write(""); } + out.write(" static Ticks timestamp(void);"); + out.write(" static Ticks _timestamp;"); + out.write(" static PeriodicType type(void);"); + out.write(" static PeriodicType _type;"); out.write("};"); out.write(""); out.write("#endif // INCLUDE_JFR"); diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index ba21e1f60e6..83c9a2377ca 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -874,7 +874,7 @@ BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm ifeq ($(call isTargetOs, windows), true) BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT - BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libTestPsig.c + BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libTestPsig.c libnativeStack.c BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libatExit := jvm.lib BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exedaemonDestroy := jvm.lib else @@ -1515,6 +1515,7 @@ else BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libterminatedThread += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libatExit += -ljvm BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libCompleteExit += -lpthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativeStack += -lpthread endif # This evaluation is expensive and should only be done if this target was diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index e6d39248ac4..e6c2cc79ff1 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2021, Red Hat, Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -1739,7 +1739,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { st->print("\n\t"); st->print("ldr rscratch1, [guard]\n\t"); st->print("dmb ishld\n\t"); - st->print("ldr rscratch2, [rthread, #thread_disarmed_offset]\n\t"); + st->print("ldr rscratch2, [rthread, #thread_disarmed_guard_value_offset]\n\t"); st->print("cmp rscratch1, rscratch2\n\t"); st->print("b.eq skip"); st->print("\n\t"); @@ -1796,8 +1796,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label* guard = &dummy_guard; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for the purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); guard = &stub->guard(); } @@ -1879,7 +1880,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); @@ -3632,6 +3635,11 @@ encode %{ ciEnv::current()->record_failure("CodeCache is full"); return; } + } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) { + // The NOP here is purely to ensure that eliding a call to + // JVM_EnsureMaterializedForStackWalk doesn't change the code size. + __ nop(); + __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); } else { int method_index = resolved_method_index(cbuf); RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) @@ -7550,7 +7558,7 @@ instruct storeimmL0(immL0 zero, memory8 mem) instruct storeP(iRegP src, memory8 mem) %{ match(Set mem (StoreP mem src)); - predicate(!needs_releasing_store(n)); + predicate(!needs_releasing_store(n) && n->as_Store()->barrier_data() == 0); ins_cost(INSN_COST); format %{ "str $src, $mem\t# ptr" %} @@ -7564,7 +7572,7 @@ instruct storeP(iRegP src, memory8 mem) instruct storeimmP0(immP0 zero, memory8 mem) %{ match(Set mem (StoreP mem zero)); - predicate(!needs_releasing_store(n)); + predicate(!needs_releasing_store(n) && n->as_Store()->barrier_data() == 0); ins_cost(INSN_COST); format %{ "str zr, $mem\t# ptr" %} @@ -7965,6 +7973,7 @@ instruct storeimmL0_volatile(immL0 zero, /* sync_memory*/indirect mem) instruct storeP_volatile(iRegP src, /* sync_memory*/indirect mem) %{ match(Set mem (StoreP mem src)); + predicate(n->as_Store()->barrier_data() == 0); ins_cost(VOLATILE_REF_COST); format %{ "stlr $src, $mem\t# ptr" %} @@ -7977,6 +7986,7 @@ instruct storeP_volatile(iRegP src, /* sync_memory*/indirect mem) instruct storeimmP0_volatile(immP0 zero, /* sync_memory*/indirect mem) %{ match(Set mem (StoreP mem zero)); + predicate(n->as_Store()->barrier_data() == 0); ins_cost(VOLATILE_REF_COST); format %{ "stlr zr, $mem\t# ptr" %} @@ -9646,6 +9656,90 @@ instruct get_and_addIi_no_resAcq(indirect mem, Universe dummy, immIAddSub incr) ins_pipe(pipe_serial); %} +// Manifest a CmpU result in an integer register. +// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) +instruct cmpU3_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg flags) +%{ + match(Set dst (CmpU3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "cmpw $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpU3(reg)" + %} + ins_encode %{ + __ cmpw($src1$$Register, $src2$$Register); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpU3_reg_imm(iRegINoSp dst, iRegI src1, immIAddSub src2, rFlagsReg flags) +%{ + match(Set dst (CmpU3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "subsw zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpU3(imm)" + %} + ins_encode %{ + __ subsw(zr, $src1$$Register, (int32_t)$src2$$constant); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +// Manifest a CmpUL result in an integer register. +// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) +instruct cmpUL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) +%{ + match(Set dst (CmpUL3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "cmp $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpUL3(reg)" + %} + ins_encode %{ + __ cmp($src1$$Register, $src2$$Register); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpUL3_reg_imm(iRegINoSp dst, iRegL src1, immLAddSub src2, rFlagsReg flags) +%{ + match(Set dst (CmpUL3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "subs zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpUL3(imm)" + %} + ins_encode %{ + __ subs(zr, $src1$$Register, (int32_t)$src2$$constant); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + // Manifest a CmpL result in an integer register. // (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) instruct cmpL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) @@ -9653,13 +9747,12 @@ instruct cmpL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) match(Set dst (CmpL3 src1 src2)); effect(KILL flags); - ins_cost(INSN_COST * 6); + ins_cost(INSN_COST * 3); format %{ - "cmp $src1, $src2" - "csetw $dst, ne" - "cnegw $dst, lt" + "cmp $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lt\t# CmpL3(reg)" %} - // format %{ "CmpL3 $dst, $src1, $src2" %} ins_encode %{ __ cmp($src1$$Register, $src2$$Register); __ csetw($dst$$Register, Assembler::NE); @@ -9674,19 +9767,14 @@ instruct cmpL3_reg_imm(iRegINoSp dst, iRegL src1, immLAddSub src2, rFlagsReg fla match(Set dst (CmpL3 src1 src2)); effect(KILL flags); - ins_cost(INSN_COST * 6); + ins_cost(INSN_COST * 3); format %{ - "cmp $src1, $src2" - "csetw $dst, ne" - "cnegw $dst, lt" + "subs zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lt\t# CmpL3(imm)" %} ins_encode %{ - int32_t con = (int32_t)$src2$$constant; - if (con < 0) { - __ adds(zr, $src1$$Register, -con); - } else { - __ subs(zr, $src1$$Register, con); - } + __ subs(zr, $src1$$Register, (int32_t)$src2$$constant); __ csetw($dst$$Register, Assembler::NE); __ cnegw($dst$$Register, $dst$$Register, Assembler::LT); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 7868d7cf46b..c67d43a2c34 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -132,6 +132,11 @@ source %{ // Vector API intrinsics. if ((opcode == Op_VectorCastD2X && bt == T_INT) || (opcode == Op_VectorCastL2X && bt == T_FLOAT) || + (opcode == Op_CountLeadingZerosV && bt == T_LONG) || + (opcode == Op_CountTrailingZerosV && bt == T_LONG) || + // The vector implementation of Op_AddReductionVD/F is for the Vector API only. + // It is not suitable for auto-vectorization because it does not add the elements + // in the same order as sequential code, and FP addition is non-associative. opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -2874,23 +2879,30 @@ instruct reduce_addL_sve(iRegLNoSp dst, iRegL isrc, vReg vsrc, vRegD tmp) %{ %} // reduction addF +// Floating-point addition is not associative, so the rules for AddReductionVF +// on NEON can't be used to auto-vectorize floating-point reduce-add. +// Currently, on NEON, AddReductionVF is only generated by Vector API. +instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ + predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 2); + match(Set dst (AddReductionVF fsrc vsrc)); + effect(TEMP_DEF dst); + format %{ "reduce_add2F_neon $dst, $fsrc, $vsrc" %} + ins_encode %{ + __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ S); + __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); + %} + ins_pipe(pipe_slow); +%} -instruct reduce_addF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ - predicate(UseSVE == 0); +instruct reduce_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ + predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 4); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_addF_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} + format %{ "reduce_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc); - __ fadds($dst$$FloatRegister, $fsrc$$FloatRegister, $vsrc$$FloatRegister); - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 1); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - if (length_in_bytes == 16) { - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 2); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 3); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - } + __ faddp($tmp$$FloatRegister, __ T4S, $vsrc$$FloatRegister, $vsrc$$FloatRegister); + __ faddp($dst$$FloatRegister, $tmp$$FloatRegister, __ S); + __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); %} ins_pipe(pipe_slow); %} @@ -2908,16 +2920,17 @@ instruct reduce_addF_sve(vRegF dst_src1, vReg src2) %{ %} // reduction addD - -instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc, vReg tmp) %{ +// Floating-point addition is not associative, so the rule for AddReductionVD +// on NEON can't be used to auto-vectorize floating-point reduce-add. +// Currently, on NEON, AddReductionVD is only generated by Vector API. +instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ predicate(UseSVE == 0); match(Set dst (AddReductionVD dsrc vsrc)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %} + effect(TEMP_DEF dst); + format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D" %} ins_encode %{ - __ faddd($dst$$FloatRegister, $dsrc$$FloatRegister, $vsrc$$FloatRegister); - __ ins($tmp$$FloatRegister, __ D, $vsrc$$FloatRegister, 0, 1); - __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); + __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ D); + __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $dsrc$$FloatRegister); %} ins_pipe(pipe_slow); %} @@ -5672,7 +5685,6 @@ instruct vpopcountI(vReg dst, vReg src) %{ // vector popcount - LONG instruct vpopcountL(vReg dst, vReg src) %{ - predicate(Matcher::vector_element_basic_type(n) == T_LONG); match(Set dst (PopCountVL src)); format %{ "vpopcountL $dst, $src" %} ins_encode %{ @@ -5688,32 +5700,6 @@ instruct vpopcountL(vReg dst, vReg src) %{ ins_pipe(pipe_slow); %} -// If the PopCountVL is generated by auto-vectorization, the dst basic -// type is T_INT. And once we have unified the type definition for -// Vector API and auto-vectorization, this rule can be merged with -// "vpopcountL" rule. - -instruct vpopcountL_I(vReg dst, vReg src, vReg tmp) %{ - predicate(Matcher::vector_element_basic_type(n) == T_INT); - match(Set dst (PopCountVL src)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "vpopcountL_I $dst, $src\t# KILL $tmp" %} - ins_encode %{ - if (UseSVE == 0) { - __ cnt($dst$$FloatRegister, __ T16B, $src$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T16B, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T8H, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T4S, $dst$$FloatRegister); - __ xtn($dst$$FloatRegister, __ T2S, $dst$$FloatRegister, __ T2D); - } else { - __ sve_cnt($dst$$FloatRegister, __ D, ptrue, $src$$FloatRegister); - __ sve_vector_narrow($dst$$FloatRegister, __ S, - $dst$$FloatRegister, __ D, $tmp$$FloatRegister); - } - %} - ins_pipe(pipe_slow); -%} - // vector popcount - predicated instruct vpopcountI_masked(vReg dst_src, pRegGov pg) %{ @@ -5729,7 +5715,7 @@ instruct vpopcountI_masked(vReg dst_src, pRegGov pg) %{ %} instruct vpopcountL_masked(vReg dst_src, pRegGov pg) %{ - predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); + predicate(UseSVE > 0); match(Set dst_src (PopCountVL dst_src pg)); format %{ "vpopcountL_masked $dst_src, $pg, $dst_src" %} ins_encode %{ @@ -5894,67 +5880,62 @@ instruct vroundD(vReg dst, vReg src, immI rmode) %{ // anytrue -instruct vtest_anytrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_anytrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP tmp, KILL cr); - format %{ "vtest_anytrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_anytrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ addv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, zr); - __ csetw($dst$$Register, Assembler::NE); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, zr); %} ins_pipe(pipe_slow); %} -instruct vtest_anytrue_sve(iRegINoSp dst, pReg src1, pReg src2, rFlagsReg cr) %{ +instruct vtest_anytrue_sve(rFlagsReg cr, pReg src1, pReg src2) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vtest_anytrue_sve $dst, $src1\t# KILL cr" %} + match(Set cr (VectorTest src1 src2)); + format %{ "vtest_anytrue_sve $src1" %} ins_encode %{ // "src2" is not used for sve. __ sve_ptest(ptrue, $src1$$PRegister); - __ csetw($dst$$Register, Assembler::NE); %} ins_pipe(pipe_slow); %} // alltrue -instruct vtest_alltrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_alltrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP tmp, KILL cr); - format %{ "vtest_alltrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_alltrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ uminv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, 0xff); - __ csetw($dst$$Register, Assembler::EQ); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, 0xff); %} ins_pipe(pipe_slow); %} -instruct vtest_alltrue_sve(iRegINoSp dst, pReg src1, pReg src2, pReg ptmp, rFlagsReg cr) %{ +instruct vtest_alltrue_sve(rFlagsReg cr, pReg src1, pReg src2, pReg ptmp) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP ptmp, KILL cr); - format %{ "vtest_alltrue_sve $dst, $src1, $src2\t# KILL $ptmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP ptmp); + format %{ "vtest_alltrue_sve $src1, $src2\t# KILL $ptmp" %} ins_encode %{ __ sve_eors($ptmp$$PRegister, ptrue, $src1$$PRegister, $src2$$PRegister); - __ csetw($dst$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index 118611b1675..b59e1ae43fa 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -122,6 +122,11 @@ source %{ // Vector API intrinsics. if ((opcode == Op_VectorCastD2X && bt == T_INT) || (opcode == Op_VectorCastL2X && bt == T_FLOAT) || + (opcode == Op_CountLeadingZerosV && bt == T_LONG) || + (opcode == Op_CountTrailingZerosV && bt == T_LONG) || + // The vector implementation of Op_AddReductionVD/F is for the Vector API only. + // It is not suitable for auto-vectorization because it does not add the elements + // in the same order as sequential code, and FP addition is non-associative. opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -1806,23 +1811,30 @@ REDUCE_ADD_INT_NEON_SVE_PAIRWISE(I, iRegIorL2I) REDUCE_ADD_INT_NEON_SVE_PAIRWISE(L, iRegL) // reduction addF +// Floating-point addition is not associative, so the rules for AddReductionVF +// on NEON can't be used to auto-vectorize floating-point reduce-add. +// Currently, on NEON, AddReductionVF is only generated by Vector API. +instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ + predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 2); + match(Set dst (AddReductionVF fsrc vsrc)); + effect(TEMP_DEF dst); + format %{ "reduce_add2F_neon $dst, $fsrc, $vsrc" %} + ins_encode %{ + __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ S); + __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); + %} + ins_pipe(pipe_slow); +%} -instruct reduce_addF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ - predicate(UseSVE == 0); +instruct reduce_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ + predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 4); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_addF_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} + format %{ "reduce_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc); - __ fadds($dst$$FloatRegister, $fsrc$$FloatRegister, $vsrc$$FloatRegister); - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 1); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - if (length_in_bytes == 16) { - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 2); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - __ ins($tmp$$FloatRegister, __ S, $vsrc$$FloatRegister, 0, 3); - __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); - } + __ faddp($tmp$$FloatRegister, __ T4S, $vsrc$$FloatRegister, $vsrc$$FloatRegister); + __ faddp($dst$$FloatRegister, $tmp$$FloatRegister, __ S); + __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); %} ins_pipe(pipe_slow); %} @@ -1845,16 +1857,17 @@ dnl REDUCE_ADD_FP_SVE(F, S) // reduction addD - -instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc, vReg tmp) %{ +// Floating-point addition is not associative, so the rule for AddReductionVD +// on NEON can't be used to auto-vectorize floating-point reduce-add. +// Currently, on NEON, AddReductionVD is only generated by Vector API. +instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ predicate(UseSVE == 0); match(Set dst (AddReductionVD dsrc vsrc)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %} + effect(TEMP_DEF dst); + format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D" %} ins_encode %{ - __ faddd($dst$$FloatRegister, $dsrc$$FloatRegister, $vsrc$$FloatRegister); - __ ins($tmp$$FloatRegister, __ D, $vsrc$$FloatRegister, 0, 1); - __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $tmp$$FloatRegister); + __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ D); + __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $dsrc$$FloatRegister); %} ins_pipe(pipe_slow); %} @@ -4055,7 +4068,6 @@ instruct vpopcountI(vReg dst, vReg src) %{ // vector popcount - LONG instruct vpopcountL(vReg dst, vReg src) %{ - predicate(Matcher::vector_element_basic_type(n) == T_LONG); match(Set dst (PopCountVL src)); format %{ "vpopcountL $dst, $src" %} ins_encode %{ @@ -4071,37 +4083,11 @@ instruct vpopcountL(vReg dst, vReg src) %{ ins_pipe(pipe_slow); %} -// If the PopCountVL is generated by auto-vectorization, the dst basic -// type is T_INT. And once we have unified the type definition for -// Vector API and auto-vectorization, this rule can be merged with -// "vpopcountL" rule. - -instruct vpopcountL_I(vReg dst, vReg src, vReg tmp) %{ - predicate(Matcher::vector_element_basic_type(n) == T_INT); - match(Set dst (PopCountVL src)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "vpopcountL_I $dst, $src\t# KILL $tmp" %} - ins_encode %{ - if (UseSVE == 0) { - __ cnt($dst$$FloatRegister, __ T16B, $src$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T16B, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T8H, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T4S, $dst$$FloatRegister); - __ xtn($dst$$FloatRegister, __ T2S, $dst$$FloatRegister, __ T2D); - } else { - __ sve_cnt($dst$$FloatRegister, __ D, ptrue, $src$$FloatRegister); - __ sve_vector_narrow($dst$$FloatRegister, __ S, - $dst$$FloatRegister, __ D, $tmp$$FloatRegister); - } - %} - ins_pipe(pipe_slow); -%} - // vector popcount - predicated UNARY_OP_PREDICATE(vpopcountI, PopCountVI, sve_cnt) instruct vpopcountL_masked(vReg dst_src, pRegGov pg) %{ - predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); + predicate(UseSVE > 0); match(Set dst_src (PopCountVL dst_src pg)); format %{ "vpopcountL_masked $dst_src, $pg, $dst_src" %} ins_encode %{ @@ -4266,67 +4252,62 @@ instruct vroundD(vReg dst, vReg src, immI rmode) %{ // anytrue -instruct vtest_anytrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_anytrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP tmp, KILL cr); - format %{ "vtest_anytrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_anytrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ addv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, zr); - __ csetw($dst$$Register, Assembler::NE); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, zr); %} ins_pipe(pipe_slow); %} -instruct vtest_anytrue_sve(iRegINoSp dst, pReg src1, pReg src2, rFlagsReg cr) %{ +instruct vtest_anytrue_sve(rFlagsReg cr, pReg src1, pReg src2) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vtest_anytrue_sve $dst, $src1\t# KILL cr" %} + match(Set cr (VectorTest src1 src2)); + format %{ "vtest_anytrue_sve $src1" %} ins_encode %{ // "src2" is not used for sve. __ sve_ptest(ptrue, $src1$$PRegister); - __ csetw($dst$$Register, Assembler::NE); %} ins_pipe(pipe_slow); %} // alltrue -instruct vtest_alltrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_alltrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP tmp, KILL cr); - format %{ "vtest_alltrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_alltrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ uminv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, 0xff); - __ csetw($dst$$Register, Assembler::EQ); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, 0xff); %} ins_pipe(pipe_slow); %} -instruct vtest_alltrue_sve(iRegINoSp dst, pReg src1, pReg src2, pReg ptmp, rFlagsReg cr) %{ +instruct vtest_alltrue_sve(rFlagsReg cr, pReg src1, pReg src2, pReg ptmp) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP ptmp, KILL cr); - format %{ "vtest_alltrue_sve $dst, $src1, $src2\t# KILL $ptmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP ptmp); + format %{ "vtest_alltrue_sve $src1, $src2\t# KILL $ptmp" %} ins_encode %{ __ sve_eors($ptmp$$PRegister, ptrue, $src1$$PRegister, $src2$$PRegister); - __ csetw($dst$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index b05c0e800e8..3cd87e254b3 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -505,7 +505,20 @@ class Address { } bool uses(Register reg) const { - return base() == reg || index() == reg; + switch (_mode) { + case literal: + case no_mode: + return false; + case base_plus_offset: + case base_plus_offset_reg: + case pre: + case post: + case post_reg: + return base() == reg || index() == reg; + default: + ShouldNotReachHere(); + return false; + } } address target() const { @@ -2435,6 +2448,7 @@ void mvnw(Register Rd, Register Rm, break; default: ShouldNotReachHere(); + Rm = 0; // unreachable } starti; @@ -2715,6 +2729,7 @@ template INSN(fabd, 1, 1, 0b110101); INSN(fadd, 0, 0, 0b110101); INSN(fdiv, 1, 0, 0b111111); + INSN(faddp, 1, 0, 0b110101); INSN(fmul, 1, 0, 0b110111); INSN(fsub, 0, 1, 0b110101); INSN(fmla, 0, 0, 0b110011); diff --git a/src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp index 9072d09f18c..e92c538637f 100644 --- a/src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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. * @@ -78,4 +78,8 @@ enum { pd_float_saved_as_double = false }; +enum { + pd_two_operand_lir_form = false +}; + #endif // CPU_AARCH64_C1_DEFS_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index aa51335c4c2..3aa7acf71b3 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -199,9 +199,12 @@ void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int mov(rscratch1, len_in_bytes); lea(t1, Address(obj, hdr_size_in_bytes)); lsr(t2, rscratch1, LogBytesPerWord); - zero_words(t1, t2); + address tpc = zero_words(t1, t2); bind(done); + if (tpc == nullptr) { + Compilation::current()->bailout("no space for trampoline stub"); + } } @@ -228,10 +231,17 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register if (var_size_in_bytes != noreg) { mov(index, var_size_in_bytes); initialize_body(obj, index, hdr_size_in_bytes, t1, t2); + if (Compilation::current()->bailed_out()) { + return; + } } else if (con_size_in_bytes > hdr_size_in_bytes) { con_size_in_bytes -= hdr_size_in_bytes; lea(t1, Address(obj, hdr_size_in_bytes)); - zero_words(t1, con_size_in_bytes / BytesPerWord); + address tpc = zero_words(t1, con_size_in_bytes / BytesPerWord); + if (tpc == nullptr) { + Compilation::current()->bailout("no space for trampoline stub"); + return; + } } } @@ -267,6 +277,9 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, // clear rest of allocated space initialize_body(obj, arr_size, header_size * BytesPerWord, t1, t2); + if (Compilation::current()->bailed_out()) { + return; + } membar(StoreStore); diff --git a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp index 50bbbd786d9..c2d1405b005 100644 --- a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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. * @@ -60,6 +60,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, true ); define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, false ); #endif // CPU_AARCH64_C1_GLOBALS_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp similarity index 65% rename from src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp rename to src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp index fb36406fbde..009883d6082 100644 --- a/src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,24 +23,44 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 20; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(masm.pc() - masm.offset() + _safepoint_offset); __ adr(rscratch1, safepoint_pc); __ str(rscratch1, Address(rthread, JavaThread::saved_exception_pc_offset())); __ far_jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + return 24; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + __ movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier()); + __ blr(rscratch1); + __ b(continuation()); + + __ bind(guard()); + __ relocate(entry_guard_Relocation::spec()); + __ emit_int32(0); // nmethod guard value +} + #undef __ diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 93495e0fc58..121b2b96209 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -45,21 +45,6 @@ typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr); -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - bind(stub->slow_path()); - movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier()); - blr(rscratch1); - b(stub->continuation()); - - bind(stub->guard()); - relocate(entry_guard_Relocation::spec()); - emit_int32(0); // nmethod guard value -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 4 * 6; -} - // Search for str1 in str2 and return index or -1 void C2_MacroAssembler::string_indexof(Register str2, Register str1, Register cnt2, Register cnt1, @@ -313,7 +298,12 @@ void C2_MacroAssembler::string_indexof(Register str2, Register str1, stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_uu()); assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); } - trampoline_call(stub); + address call = trampoline_call(stub); + if (call == nullptr) { + DEBUG_ONLY(reset_labels(LINEARSEARCH, LINEAR_MEDIUM, DONE, NOMATCH, MATCH)); + ciEnv::current()->record_failure("CodeCache is full"); + return; + } b(DONE); } @@ -872,7 +862,12 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, ShouldNotReachHere(); } assert(stub.target() != NULL, "compare_long_string stub has not been generated"); - trampoline_call(stub); + address call = trampoline_call(stub); + if (call == nullptr) { + DEBUG_ONLY(reset_labels(DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, SHORT_LOOP_START)); + ciEnv::current()->record_failure("CodeCache is full"); + return; + } b(DONE); bind(SHORT_STRING); diff --git a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp index a4213707afb..3bc12a1f651 100644 --- a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp @@ -52,7 +52,14 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline bool p_succeeded = true; auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) { masm.set_code_section(cb->stubs()); - masm.align(wordSize); + if (!is_aligned(masm.offset(), wordSize)) { + if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + p_succeeded = false; + return p_succeeded; + } + masm.align(wordSize); + } LinkedListIterator it(offsets.head()); int offset = *it.next(); diff --git a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp index 79976b84d0a..6075c09f8d2 100644 --- a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp @@ -196,11 +196,6 @@ inline void ThawBase::prefetch_chunk_pd(void* start, int size) { Prefetch::read(start, size - 64); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - frame::sender_sp_offset) = fp; -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { // Fast path depends on !PreserveFramePointer. See can_thaw_fast(). diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index a46a8be39d1..9f740098e19 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -42,13 +42,14 @@ class DowncallStubGenerator : public StubCodeGenerator { BasicType _ret_bt; const ABIDescriptor& _abi; - const GrowableArray& _input_registers; - const GrowableArray& _output_registers; + const GrowableArray& _input_registers; + const GrowableArray& _output_registers; bool _needs_return_buffer; + int _captured_state_mask; int _frame_complete; - int _framesize; + int _frame_size_slots; OopMapSet* _oop_maps; public: DowncallStubGenerator(CodeBuffer* buffer, @@ -56,9 +57,10 @@ class DowncallStubGenerator : public StubCodeGenerator { int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) : StubCodeGenerator(buffer, PrintMethodHandleStubs), _signature(signature), _num_args(num_args), @@ -67,8 +69,9 @@ class DowncallStubGenerator : public StubCodeGenerator { _input_registers(input_registers), _output_registers(output_registers), _needs_return_buffer(needs_return_buffer), + _captured_state_mask(captured_state_mask), _frame_complete(0), - _framesize(0), + _frame_size_slots(0), _oop_maps(NULL) { } @@ -79,7 +82,7 @@ class DowncallStubGenerator : public StubCodeGenerator { } int framesize() const { - return (_framesize >> (LogBytesPerWord - LogBytesPerInt)); + return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt)); } OopMapSet* oop_maps() const { @@ -93,12 +96,15 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { - int locs_size = 64; + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { + int locs_size = 64; CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size); - DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer); + DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, + input_registers, output_registers, + needs_return_buffer, captured_state_mask); g.generate(); code.log_section_sizes("nep_invoker_blob"); @@ -137,10 +143,10 @@ void DowncallStubGenerator::generate() { Register tmp1 = r9; Register tmp2 = r10; - Register shuffle_reg = r19; + VMStorage shuffle_reg = as_VMStorage(r19); JavaCallingConvention in_conv; NativeCallingConvention out_conv(_input_registers); - ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); + ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg); #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; @@ -152,32 +158,36 @@ void DowncallStubGenerator::generate() { #endif int allocated_frame_size = 0; - if (_needs_return_buffer) { - allocated_frame_size += 8; // for address spill - } - allocated_frame_size += arg_shuffle.out_arg_stack_slots() < allocated_frame_size ? out_reg_spiller.spill_size_bytes() : allocated_frame_size; } - _framesize = align_up(framesize - + (allocated_frame_size >> LogBytesPerInt), 4); - assert(is_even(_framesize/2), "sp not 16-byte aligned"); + StubLocations locs; + locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch1); + if (_needs_return_buffer) { + locs.set_frame_data(StubLocations::RETURN_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; // for address spill + } + if (_captured_state_mask != 0) { + locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + + _frame_size_slots = align_up(framesize + (allocated_frame_size >> LogBytesPerInt), 4); + assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned"); _oop_maps = new OopMapSet(); address start = __ pc(); @@ -185,13 +195,13 @@ void DowncallStubGenerator::generate() { __ enter(); // lr and fp are already in place - __ sub(sp, rfp, ((unsigned)_framesize-4) << LogBytesPerInt); // prolog + __ sub(sp, rfp, ((unsigned)_frame_size_slots-4) << LogBytesPerInt); // prolog _frame_complete = __ pc() - start; address the_pc = __ pc(); __ set_last_Java_frame(sp, rfp, the_pc, tmp1); - OopMap* map = new OopMap(_framesize, 0); + OopMap* map = new OopMap(_frame_size_slots, 0); _oop_maps->add_gc_map(the_pc - start, map); // State transition @@ -200,43 +210,22 @@ void DowncallStubGenerator::generate() { __ stlrw(tmp1, tmp2); __ block_comment("{ argument shuffle"); - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes); - if (_needs_return_buffer) { - assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill"); - __ str(_abi._ret_buf_addr_reg, Address(sp, ret_buf_addr_sp_offset)); - } + arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs); __ block_comment("} argument shuffle"); - __ blr(_abi._target_addr_reg); + __ blr(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed rthread - if (!_needs_return_buffer) { - // Unpack native results. - switch (_ret_bt) { - case T_BOOLEAN: __ c2bool(r0); break; - case T_CHAR : __ ubfx(r0, r0, 0, 16); break; - case T_BYTE : __ sbfx(r0, r0, 0, 8); break; - case T_SHORT : __ sbfx(r0, r0, 0, 16); break; - case T_INT : __ sbfx(r0, r0, 0, 32); break; - case T_DOUBLE : - case T_FLOAT : - // Result is in v0 we'll save as needed - break; - case T_VOID: break; - case T_LONG: break; - default : ShouldNotReachHere(); - } - } else { - assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill"); - __ ldr(tmp1, Address(sp, ret_buf_addr_sp_offset)); + if (_needs_return_buffer) { + __ ldr(tmp1, Address(sp, locs.data_offset(StubLocations::RETURN_BUFFER))); int offset = 0; for (int i = 0; i < _output_registers.length(); i++) { - VMReg reg = _output_registers.at(i); - if (reg->is_Register()) { - __ str(reg->as_Register(), Address(tmp1, offset)); + VMStorage reg = _output_registers.at(i); + if (reg.type() == StorageType::INTEGER) { + __ str(as_Register(reg), Address(tmp1, offset)); offset += 8; - } else if(reg->is_FloatRegister()) { - __ strd(reg->as_FloatRegister(), Address(tmp1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ strd(as_FloatRegister(reg), Address(tmp1, offset)); offset += 16; } else { ShouldNotReachHere(); @@ -244,6 +233,28 @@ void DowncallStubGenerator::generate() { } } + ////////////////////////////////////////////////////////////////////////////// + + if (_captured_state_mask != 0) { + __ block_comment("{ save thread local"); + + if (should_save_return_value) { + out_reg_spiller.generate_spill(_masm, spill_offset); + } + + __ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movw(c_rarg1, _captured_state_mask); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state), tmp1); + + if (should_save_return_value) { + out_reg_spiller.generate_fill(_masm, spill_offset); + } + + __ block_comment("} save thread local"); + } + + ////////////////////////////////////////////////////////////////////////////// + __ mov(tmp1, _thread_in_native_trans); __ strw(tmp1, Address(rthread, JavaThread::thread_state_offset())); @@ -288,7 +299,7 @@ void DowncallStubGenerator::generate() { __ block_comment("{ L_safepoint_poll_slow_path"); __ bind(L_safepoint_poll_slow_path); - if (!_needs_return_buffer) { + if (should_save_return_value) { // Need to save the native result registers around any runtime calls. out_reg_spiller.generate_spill(_masm, spill_offset); } @@ -298,7 +309,7 @@ void DowncallStubGenerator::generate() { __ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ blr(tmp1); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_offset); } @@ -310,13 +321,13 @@ void DowncallStubGenerator::generate() { __ block_comment("{ L_reguard"); __ bind(L_reguard); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_offset); } __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_offset); } diff --git a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp index 6416703502e..e20c7e40601 100644 --- a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp @@ -30,6 +30,7 @@ #include "oops/oopCast.inline.hpp" #include "prims/foreignGlobals.hpp" #include "prims/foreignGlobals.inline.hpp" +#include "prims/vmstorage.hpp" #include "utilities/formatBuffer.hpp" bool ABIDescriptor::is_volatile_reg(Register reg) const { @@ -42,112 +43,183 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const { || _vector_additional_volatile_registers.contains(reg); } -static constexpr int INTEGER_TYPE = 0; -static constexpr int VECTOR_TYPE = 1; - const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { oop abi_oop = JNIHandles::resolve_non_null(jabi); ABIDescriptor abi; - constexpr Register (*to_Register)(int) = as_Register; objArrayOop inputStorage = jdk_internal_foreign_abi_ABIDescriptor::inputStorage(abi_oop); - parse_register_array(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register); - parse_register_array(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_FloatRegister); + parse_register_array(inputStorage, StorageType::INTEGER, abi._integer_argument_registers, as_Register); + parse_register_array(inputStorage, StorageType::VECTOR, abi._vector_argument_registers, as_FloatRegister); objArrayOop outputStorage = jdk_internal_foreign_abi_ABIDescriptor::outputStorage(abi_oop); - parse_register_array(outputStorage, INTEGER_TYPE, abi._integer_return_registers, to_Register); - parse_register_array(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_FloatRegister); + parse_register_array(outputStorage, StorageType::INTEGER, abi._integer_return_registers, as_Register); + parse_register_array(outputStorage, StorageType::VECTOR, abi._vector_return_registers, as_FloatRegister); objArrayOop volatileStorage = jdk_internal_foreign_abi_ABIDescriptor::volatileStorage(abi_oop); - parse_register_array(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, to_Register); - parse_register_array(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_FloatRegister); + parse_register_array(volatileStorage, StorageType::INTEGER, abi._integer_additional_volatile_registers, as_Register); + parse_register_array(volatileStorage, StorageType::VECTOR, abi._vector_additional_volatile_registers, as_FloatRegister); abi._stack_alignment_bytes = jdk_internal_foreign_abi_ABIDescriptor::stackAlignment(abi_oop); abi._shadow_space_bytes = jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(abi_oop); - abi._target_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(abi_oop))->as_Register(); - abi._ret_buf_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(abi_oop))->as_Register(); + abi._scratch1 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch1(abi_oop)); + abi._scratch2 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch2(abi_oop)); return abi; } -enum class RegType { - INTEGER = 0, - VECTOR = 1, - STACK = 3 -}; - -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - switch(static_cast(type)) { - case RegType::INTEGER: return ::as_Register(index)->as_VMReg(); - case RegType::VECTOR: return ::as_FloatRegister(index)->as_VMReg(); - case RegType::STACK: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); - } - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { - if (reg->is_Register()) { +int RegSpiller::pd_reg_size(VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { return 8; - } else if (reg->is_FloatRegister()) { + } else if (reg.type() == StorageType::VECTOR) { return 16; // Always spill/unspill Q registers } return 0; // stack and BAD } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->spill(reg->as_Register(), true, offset); - } else if (reg->is_FloatRegister()) { - masm->spill(reg->as_FloatRegister(), masm->Q, offset); +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->spill(as_Register(reg), true, offset); + } else if (reg.type() == StorageType::VECTOR) { + masm->spill(as_FloatRegister(reg), masm->Q, offset); } else { // stack and BAD } } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->unspill(reg->as_Register(), true, offset); - } else if (reg->is_FloatRegister()) { - masm->unspill(reg->as_FloatRegister(), masm->Q, offset); +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->unspill(as_Register(reg), true, offset); + } else if (reg.type() == StorageType::VECTOR) { + masm->unspill(as_FloatRegister(reg), masm->Q, offset); } else { // stack and BAD } } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { - assert(in_stk_bias == 0 && out_stk_bias == 0, "bias not implemented"); - Register tmp_reg = tmp->as_Register(); +static constexpr int RFP_BIAS = 16; // skip old rfp and lr + +static void move_reg64(MacroAssembler* masm, int out_stk_bias, + Register from_reg, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->mov(as_Register(to_reg), from_reg); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: { + Address dest(sp, to_reg.offset() + out_bias); + switch (to_reg.stack_size()) { + case 8: masm->str (from_reg, dest); break; + case 4: masm->strw(from_reg, dest); break; + case 2: masm->strh(from_reg, dest); break; + case 1: masm->strb(from_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +static void move_stack(MacroAssembler* masm, Register tmp_reg, int in_stk_bias, int out_stk_bias, + VMStorage from_reg, VMStorage to_reg) { + Address from_addr(rfp, RFP_BIAS + from_reg.offset() + in_stk_bias); + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + switch (from_reg.stack_size()) { + case 8: masm->ldr (as_Register(to_reg), from_addr); break; + case 4: masm->ldrw(as_Register(to_reg), from_addr); break; + case 2: masm->ldrh(as_Register(to_reg), from_addr); break; + case 1: masm->ldrb(as_Register(to_reg), from_addr); break; + default: ShouldNotReachHere(); + } + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == V128_MASK, "only moves to v128 registers supported"); + switch (from_reg.stack_size()) { + case 8: + masm->ldrd(as_FloatRegister(to_reg), from_addr); + break; + case 4: + masm->ldrs(as_FloatRegister(to_reg), from_addr); + break; + default: ShouldNotReachHere(); + } + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: { + switch (from_reg.stack_size()) { + case 8: masm->ldr (tmp_reg, from_addr); break; + case 4: masm->ldrw(tmp_reg, from_addr); break; + case 2: masm->ldrh(tmp_reg, from_addr); break; + case 1: masm->ldrb(tmp_reg, from_addr); break; + default: ShouldNotReachHere(); + } + Address dest(sp, to_reg.offset() + out_bias); + switch (to_reg.stack_size()) { + case 8: masm->str (tmp_reg, dest); break; + case 4: masm->strw(tmp_reg, dest); break; + case 2: masm->strh(tmp_reg, dest); break; + case 1: masm->strb(tmp_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +static void move_v128(MacroAssembler* masm, int out_stk_bias, + FloatRegister from_reg, VMStorage to_reg) { + switch (to_reg.type()) { + case StorageType::VECTOR: + assert(to_reg.segment_mask() == V128_MASK, "only moves to v128 registers supported"); + masm->fmovd(as_FloatRegister(to_reg), from_reg); + break; + case StorageType::STACK: { + Address dest(sp, to_reg.offset() + out_stk_bias); + switch (to_reg.stack_size()) { + case 8: masm->strd(from_reg, dest); break; + case 4: masm->strs(from_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { + Register tmp_reg = as_Register(tmp); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; - VMRegPair from_vmreg = move.from; - VMRegPair to_vmreg = move.to; - - masm->block_comment(err_msg("bt=%s", null_safe_string(type2name(arg_bt)))); - switch (arg_bt) { - case T_BOOLEAN: - case T_BYTE: - case T_SHORT: - case T_CHAR: - case T_INT: - masm->move32_64(from_vmreg, to_vmreg, tmp_reg); - break; + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; - case T_FLOAT: - masm->float_move(from_vmreg, to_vmreg, tmp_reg); - break; + // replace any placeholders + if (from_reg.type() == StorageType::PLACEHOLDER) { + from_reg = locs.get(from_reg); + } + if (to_reg.type() == StorageType::PLACEHOLDER) { + to_reg = locs.get(to_reg); + } - case T_DOUBLE: - masm->double_move(from_vmreg, to_vmreg, tmp_reg); + switch (from_reg.type()) { + case StorageType::INTEGER: + assert(from_reg.segment_mask() == REG64_MASK, "only 64-bit register supported"); + move_reg64(masm, out_stk_bias, as_Register(from_reg), to_reg); break; - - case T_LONG : - masm->long_move(from_vmreg, to_vmreg, tmp_reg); + case StorageType::VECTOR: + assert(from_reg.segment_mask() == V128_MASK, "only v128 register supported"); + move_v128(masm, out_stk_bias, as_FloatRegister(from_reg), to_reg); break; - - default: - fatal("found in upcall args: %s", type2name(arg_bt)); + case StorageType::STACK: + move_stack(masm, tmp_reg, in_stk_bias, out_stk_bias, from_reg, to_reg); + break; + default: ShouldNotReachHere(); } } } diff --git a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp index 4555b44f528..c4f11266871 100644 --- a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp @@ -42,8 +42,8 @@ struct ABIDescriptor { int32_t _stack_alignment_bytes; int32_t _shadow_space_bytes; - Register _target_addr_reg; - Register _ret_buf_addr_reg; + VMStorage _scratch1; + VMStorage _scratch2; bool is_volatile_reg(Register reg) const; bool is_volatile_reg(FloatRegister reg) const; diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index c076f4312b1..3ea2cc5e6ac 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -734,12 +734,12 @@ extern "C" void pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx, uintptr_t thread) { if (!reg_map) { reg_map = NEW_C_HEAP_OBJ(RegisterMap, mtInternal); - ::new (reg_map) RegisterMap((JavaThread*)thread, + ::new (reg_map) RegisterMap(reinterpret_cast(thread), RegisterMap::UpdateMap::skip, RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); } else { - *reg_map = RegisterMap((JavaThread*)thread, + *reg_map = RegisterMap(reinterpret_cast(thread), RegisterMap::UpdateMap::skip, RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index 7fb736d48d4..4d82b404845 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -217,7 +217,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo // instruction patching is handled with isb fences on the way back // from the safepoint to Java. So here we can do a plain conditional // branch with no fencing. - Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset())); + Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); __ ldrw(rscratch2, thread_disarmed_addr); __ cmp(rscratch1, rscratch2); } else if (patching_type == NMethodPatchingType::conc_instruction_and_data_patch) { @@ -238,7 +238,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo // Combine the guard value (low order) with the epoch value (high order). __ orr(rscratch1, rscratch1, rscratch2, Assembler::LSL, 32); // Compare the global values with the thread-local values. - Address thread_disarmed_and_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset())); + Address thread_disarmed_and_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); __ ldr(rscratch2, thread_disarmed_and_epoch_addr); __ cmp(rscratch1, rscratch2); } else { @@ -246,7 +246,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo // Subsequent loads of oops must occur after load of guard value. // BarrierSetNMethod::disarm sets guard with release semantics. __ membar(__ LoadLoad); - Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset())); + Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); __ ldrw(rscratch2, thread_disarmed_addr); __ cmpw(rscratch1, rscratch2); } diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp index 86ef613e1c4..d79705579b6 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp @@ -163,32 +163,12 @@ static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { return barrier; } -void BarrierSetNMethod::disarm(nmethod* nm) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { if (!supports_entry_barrier(nm)) { return; } - // The patching epoch is incremented before the nmethod is disarmed. Disarming - // is performed with a release store. In the nmethod entry barrier, the values - // are read in the opposite order, such that the load of the nmethod guard - // acquires the patching epoch. This way, the guard is guaranteed to block - // entries to the nmethod, until it has safely published the requirement for - // further fencing by mutators, before they are allowed to enter. - BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->increment_patching_epoch(); - - // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. - // Symmetric "LDR; DMB ISHLD" is in the nmethod barrier. - NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - barrier->set_value(nm, disarmed_value()); -} - -void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { - if (!supports_entry_barrier(nm)) { - return; - } - - if (arm_value == disarmed_value()) { + if (value == disarmed_guard_value()) { // The patching epoch is incremented before the nmethod is disarmed. Disarming // is performed with a release store. In the nmethod entry barrier, the values // are read in the opposite order, such that the load of the nmethod guard @@ -200,14 +180,14 @@ void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { } NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - barrier->set_value(nm, arm_value); + barrier->set_value(nm, value); } -bool BarrierSetNMethod::is_armed(nmethod* nm) { +int BarrierSetNMethod::guard_value(nmethod* nm) { if (!supports_entry_barrier(nm)) { - return false; + return disarmed_guard_value(); } NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - return barrier->get_value(nm) != disarmed_value(); + return barrier->get_value(nm); } diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index ff88e9487ef..b16140dac67 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -4387,7 +4387,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register tmp2) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2); @@ -4400,7 +4400,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 2f2f5cdd51a..e376d35f1e4 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1084,9 +1084,6 @@ class MacroAssembler: public Assembler { bool acquire, bool release, bool weak, Register result); -private: - void compare_eq(Register rn, Register rm, enum operand_size size); - #ifdef ASSERT // Template short-hand support to clean-up after a failed call to trampoline // call generation (see trampoline_call() below), when a set of Labels must @@ -1101,6 +1098,9 @@ class MacroAssembler: public Assembler { } #endif +private: + void compare_eq(Register rn, Register rm, enum operand_size size); + public: // AArch64 OpenJDK uses four different types of calls: // - direct call: bl pc_relative_offset diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp index a7dfe47ffb8..45b7dbf8c56 100644 --- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp @@ -163,6 +163,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // An all-set mask is used for the alltrue vector test with SVE + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return is_predicate && is_alltrue; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return is_alltrue ? BoolTest::eq : BoolTest::ne; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 82f441cf765..f7ad44aa842 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -52,9 +52,9 @@ class Register { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline Register successor() const; @@ -71,7 +71,7 @@ class Register { int operator==(const Register r) const { return _encoding == r._encoding; } int operator!=(const Register r) const { return _encoding != r._encoding; } - const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } + constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } }; extern Register::RegisterImpl all_RegisterImpls[Register::number_of_declared_registers + 1] INTERNAL_VISIBILITY; @@ -175,9 +175,9 @@ class FloatRegister { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline FloatRegister successor() const; @@ -192,7 +192,7 @@ class FloatRegister { int operator==(const FloatRegister r) const { return _encoding == r._encoding; } int operator!=(const FloatRegister r) const { return _encoding != r._encoding; } - const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; } + constexpr const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; } }; extern FloatRegister::FloatRegisterImpl all_FloatRegisterImpls[FloatRegister::number_of_registers + 1] INTERNAL_VISIBILITY; diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 7f4fcae1f93..40afbe3f065 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, 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. @@ -1103,6 +1103,9 @@ static void gen_continuation_enter(MacroAssembler* masm, __ cbnz(c_rarg2, call_thaw); const address tr_call = __ trampoline_call(resolve); + if (tr_call == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } oop_maps->add_gc_map(__ pc() - start, map); __ post_call_nop(); @@ -1110,7 +1113,10 @@ static void gen_continuation_enter(MacroAssembler* masm, __ b(exit); CodeBuffer* cbuf = masm->code_section()->outer(); - CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + if (stub == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } } // compiled entry @@ -1127,6 +1133,9 @@ static void gen_continuation_enter(MacroAssembler* masm, __ cbnz(c_rarg2, call_thaw); const address tr_call = __ trampoline_call(resolve); + if (tr_call == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } oop_maps->add_gc_map(__ pc() - start, map); __ post_call_nop(); @@ -1168,7 +1177,10 @@ static void gen_continuation_enter(MacroAssembler* masm, } CodeBuffer* cbuf = masm->code_section()->outer(); - CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + if (stub == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } } static void gen_continuation_yield(MacroAssembler* masm, diff --git a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp index 58200559181..598104264d8 100644 --- a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 484df788026..96b067b0ca2 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2022, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2361,7 +2361,10 @@ class StubGenerator: public StubCodeGenerator { __ cbnz(value, non_block_zeroing); __ mov(bz_base, to); __ add(to, to, cnt_words, Assembler::LSL, LogBytesPerWord); - __ zero_words(bz_base, cnt_words); + address tpc = __ zero_words(bz_base, cnt_words); + if (tpc == nullptr) { + fatal("CodeCache is full at generate_fill"); + } __ b(rest); __ bind(non_block_zeroing); __ fill_words(to, cnt_words, value); @@ -3246,7 +3249,7 @@ class StubGenerator: public StubCodeGenerator { __ addw(rscratch4, r1, rscratch2); __ ldrw(rscratch1, Address(buf, k*4)); __ eorw(rscratch3, rscratch3, r4); - __ addw(rscratch3, rscratch3, rscratch1); + __ addw(rscratch4, rscratch4, rscratch1); __ addw(rscratch3, rscratch3, rscratch4); __ rorw(rscratch2, rscratch3, 32 - s); __ addw(r1, rscratch2, r2); @@ -3257,13 +3260,13 @@ class StubGenerator: public StubCodeGenerator { Register rscratch3 = r10; Register rscratch4 = r11; - __ eorw(rscratch2, r2, r3); + __ andw(rscratch3, r2, r4); + __ bicw(rscratch4, r3, r4); __ ldrw(rscratch1, Address(buf, k*4)); - __ andw(rscratch3, rscratch2, r4); __ movw(rscratch2, t); - __ eorw(rscratch3, rscratch3, r3); + __ orrw(rscratch3, rscratch3, rscratch4); __ addw(rscratch4, r1, rscratch2); - __ addw(rscratch3, rscratch3, rscratch1); + __ addw(rscratch4, rscratch4, rscratch1); __ addw(rscratch3, rscratch3, rscratch4); __ rorw(rscratch2, rscratch3, 32 - s); __ addw(r1, rscratch2, r2); @@ -3279,7 +3282,7 @@ class StubGenerator: public StubCodeGenerator { __ addw(rscratch4, r1, rscratch2); __ ldrw(rscratch1, Address(buf, k*4)); __ eorw(rscratch3, rscratch3, r2); - __ addw(rscratch3, rscratch3, rscratch1); + __ addw(rscratch4, rscratch4, rscratch1); __ addw(rscratch3, rscratch3, rscratch4); __ rorw(rscratch2, rscratch3, 32 - s); __ addw(r1, rscratch2, r2); @@ -3295,7 +3298,7 @@ class StubGenerator: public StubCodeGenerator { __ addw(rscratch4, r1, rscratch3); __ ldrw(rscratch1, Address(buf, k*4)); __ eorw(rscratch3, rscratch2, r3); - __ addw(rscratch3, rscratch3, rscratch1); + __ addw(rscratch4, rscratch4, rscratch1); __ addw(rscratch3, rscratch3, rscratch4); __ rorw(rscratch2, rscratch3, 32 - s); __ addw(r1, rscratch2, r2); @@ -5331,7 +5334,7 @@ class StubGenerator: public StubCodeGenerator { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); // We can get here despite the nmethod being good, if we have not // yet applied our cross modification fence (or data fence). - Address thread_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset()) + 4); + Address thread_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()) + 4); __ lea(rscratch2, ExternalAddress(bs_asm->patching_epoch_addr())); __ ldrw(rscratch2, rscratch2); __ strw(rscratch2, thread_epoch_addr); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index eeb080d586a..eca8b7f1ca4 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -836,9 +836,12 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ stp(r10, rscratch1, Address(sp, 4 * wordSize)); // Move SP out of the way __ mov(sp, rscratch1); - } else { - __ mov(rscratch1, sp); + } else { + // Make sure there is room for the exception oop pushed in case method throws + // an exception (see TemplateInterpreterGenerator::generate_throw_exception()) + __ sub(rscratch1, sp, 2 * wordSize); __ stp(zr, rscratch1, Address(sp, 4 * wordSize)); + __ mov(sp, rscratch1); } } diff --git a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp index a051a47417e..9856fbdbdc3 100644 --- a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp @@ -128,9 +128,10 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, Register shuffle_reg = r19; JavaCallingConvention out_conv; NativeCallingConvention in_conv(call_regs._arg_regs); - ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); - int stack_slots = SharedRuntime::out_preserve_stack_slots() + arg_shuffle.out_arg_stack_slots(); - int out_arg_area = align_up(stack_slots * VMRegImpl::stack_slot_size, StackAlignmentInBytes); + ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, as_VMStorage(shuffle_reg)); + int preserved_bytes = SharedRuntime::out_preserve_stack_slots() * VMRegImpl::stack_slot_size; + int stack_bytes = preserved_bytes + arg_shuffle.out_arg_bytes(); + int out_arg_area = align_up(stack_bytes , StackAlignmentInBytes); #ifndef PRODUCT LogTarget(Trace, foreign, upcall) lt; @@ -158,10 +159,14 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, int frame_data_offset = reg_save_area_offset + reg_save_area_size; int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData); + StubLocations locs; int ret_buf_offset = -1; if (needs_return_buffer) { ret_buf_offset = frame_bottom_offset; frame_bottom_offset += ret_buf_size; + // use a free register for shuffling code to pick up return + // buffer address from + locs.set(StubLocations::RETURN_BUFFER, abi._scratch1); } int frame_size = frame_bottom_offset; @@ -218,9 +223,9 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, arg_spilller.generate_fill(_masm, arg_save_area_offset); if (needs_return_buffer) { assert(ret_buf_offset != -1, "no return buffer allocated"); - __ lea(abi._ret_buf_addr_reg, Address(sp, ret_buf_offset)); + __ lea(as_Register(locs.get(StubLocations::RETURN_BUFFER)), Address(sp, ret_buf_offset)); } - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), abi._shadow_space_bytes, 0); + arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0, locs); __ block_comment("} argument shuffle"); __ block_comment("{ receiver "); @@ -239,7 +244,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, if (!needs_return_buffer) { #ifdef ASSERT if (call_regs._ret_regs.length() == 1) { // 0 or 1 - VMReg j_expected_result_reg; + VMStorage j_expected_result_reg; switch (ret_type) { case T_BOOLEAN: case T_BYTE: @@ -247,19 +252,18 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, case T_CHAR: case T_INT: case T_LONG: - j_expected_result_reg = r0->as_VMReg(); + j_expected_result_reg = as_VMStorage(r0); break; case T_FLOAT: case T_DOUBLE: - j_expected_result_reg = v0->as_VMReg(); + j_expected_result_reg = as_VMStorage(v0); break; default: fatal("unexpected return type: %s", type2name(ret_type)); } // No need to move for now, since CallArranger can pick a return type // that goes in the same reg for both CCs. But, at least assert they are the same - assert(call_regs._ret_regs.at(0) == j_expected_result_reg, - "unexpected result register: %s != %s", call_regs._ret_regs.at(0)->name(), j_expected_result_reg->name()); + assert(call_regs._ret_regs.at(0) == j_expected_result_reg, "unexpected result register"); } #endif } else { @@ -267,12 +271,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, __ lea(rscratch1, Address(sp, ret_buf_offset)); int offset = 0; for (int i = 0; i < call_regs._ret_regs.length(); i++) { - VMReg reg = call_regs._ret_regs.at(i); - if (reg->is_Register()) { - __ ldr(reg->as_Register(), Address(rscratch1, offset)); + VMStorage reg = call_regs._ret_regs.at(i); + if (reg.type() == StorageType::INTEGER) { + __ ldr(as_Register(reg), Address(rscratch1, offset)); offset += 8; - } else if (reg->is_FloatRegister()) { - __ ldrd(reg->as_FloatRegister(), Address(rscratch1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ ldrd(as_FloatRegister(reg), Address(rscratch1, offset)); offset += 16; // needs to match VECTOR_REG_SIZE in AArch64Architecture (Java) } else { ShouldNotReachHere(); @@ -328,9 +332,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, receiver, in_ByteSize(frame_data_offset)); - if (TraceOptimizedUpcallStubs) { - blob->print_on(tty); +#ifndef PRODUCT + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + blob->print_on(&ls); } +#endif return blob->code_begin(); } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 25853cc38b1..d86d22d7fa7 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -132,7 +132,7 @@ void VM_Version::initialize() { // Enable vendor specific features // Ampere eMAG - if (_cpu == CPU_AMCC && (_model == 0) && (_variant == 0x3)) { + if (_cpu == CPU_AMCC && (_model == CPU_MODEL_EMAG) && (_variant == 0x3)) { if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) { FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true); } @@ -144,6 +144,13 @@ void VM_Version::initialize() { } } + // Ampere CPUs: Ampere-1 and Ampere-1A + if (_cpu == CPU_AMPERE && ((_model == CPU_MODEL_AMPERE_1) || (_model == CPU_MODEL_AMPERE_1A))) { + if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) { + FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true); + } + } + // ThunderX if (_cpu == CPU_CAVIUM && (_model == 0xA1)) { guarantee(_variant != 0, "Pre-release hardware no longer supported."); @@ -222,8 +229,8 @@ void VM_Version::initialize() { } char buf[512]; - sprintf(buf, "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); - if (_model2) sprintf(buf+strlen(buf), "(0x%03x)", _model2); + int buf_used_len = os::snprintf_checked(buf, sizeof(buf), "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); + if (_model2) os::snprintf_checked(buf + buf_used_len, sizeof(buf) - buf_used_len, "(0x%03x)", _model2); #define ADD_FEATURE_IF_SUPPORTED(id, name, bit) if (VM_Version::supports_##name()) strcat(buf, ", " #name); CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED) #undef ADD_FEATURE_IF_SUPPORTED diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 04e9263b930..4a977d67a6e 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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. * @@ -102,6 +102,14 @@ class VM_Version : public Abstract_VM_Version { CPU_APPLE = 'a', }; +enum Ampere_CPU_Model { + CPU_MODEL_EMAG = 0x0, /* CPU implementer is CPU_AMCC */ + CPU_MODEL_ALTRA = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */ + CPU_MODEL_ALTRAMAX = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */ + CPU_MODEL_AMPERE_1 = 0xac3, /* CPU implementer is CPU_AMPERE */ + CPU_MODEL_AMPERE_1A = 0xac4 /* CPU implementer is CPU_AMPERE */ +}; + #define CPU_FEATURE_FLAGS(decl) \ decl(FP, fp, 0) \ decl(ASIMD, asimd, 1) \ diff --git a/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp b/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp new file mode 100644 index 00000000000..7c6d34c802f --- /dev/null +++ b/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 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_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP +#define CPU_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP + +#include + +#include "asm/register.hpp" + +// keep in sync with jdk/internal/foreign/abi/aarch64/AArch64Architecture +enum class StorageType : int8_t { + INTEGER = 0, + VECTOR = 1, + STACK = 2, + PLACEHOLDER = 3, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return type == StorageType::INTEGER || type == StorageType::VECTOR; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +constexpr uint16_t REG64_MASK = 0b0000000000000001; +constexpr uint16_t V128_MASK = 0b0000000000000001; + +inline Register as_Register(VMStorage vms) { + assert(vms.type() == StorageType::INTEGER, "not the right type"); + return ::as_Register(vms.index()); +} + +inline FloatRegister as_FloatRegister(VMStorage vms) { + assert(vms.type() == StorageType::VECTOR, "not the right type"); + return ::as_FloatRegister(vms.index()); +} + +constexpr inline VMStorage as_VMStorage(Register reg) { + return VMStorage::reg_storage(StorageType::INTEGER, REG64_MASK, reg->encoding()); +} + +constexpr inline VMStorage as_VMStorage(FloatRegister reg) { + return VMStorage::reg_storage(StorageType::VECTOR, V128_MASK, reg->encoding()); +} + +inline VMStorage as_VMStorage(VMReg reg) { + if (reg->is_Register()) { + return as_VMStorage(reg->as_Register()); + } else if (reg->is_FloatRegister()) { + return as_VMStorage(reg->as_FloatRegister()); + } else if (reg->is_stack()) { + return VMStorage::stack_storage(reg); + } else if (!reg->is_valid()) { + return VMStorage::invalid(); + } + + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index ecd1c850ae4..acdbb632534 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -59,6 +59,9 @@ source_hpp %{ // To keep related declarations/definitions/uses close together, // we switch between source %{ }% and source_hpp %{ }% freely as needed. +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSetAssembler.hpp" + // Does destination need to be loaded in a register then passed to a // branch instruction? extern bool maybe_far_call(const CallNode *n); @@ -286,6 +289,17 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { if (framesize != 0) { st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize); } + + if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { + st->print("ldr t0, [guard]\n\t"); + st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t"); + st->print("cmp t0, t1\n\t"); + st->print("beq skip\n\t"); + st->print("blr #nmethod_entry_barrier_stub\n\t"); + st->print("b skip\n\t"); + st->print("guard: int\n\t"); + st->print("skip:\n\t"); + } } #endif @@ -318,6 +332,11 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { __ sub_slow(SP, SP, framesize); } + if (C->stub_function() == NULL) { + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(&_masm); + } + // offset from scratch buffer is not valid if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) { C->output()->set_frame_complete( __ offset() ); diff --git a/src/hotspot/cpu/arm/c1_Defs_arm.hpp b/src/hotspot/cpu/arm/c1_Defs_arm.hpp index b8ed431891d..68b5449cd58 100644 --- a/src/hotspot/cpu/arm/c1_Defs_arm.hpp +++ b/src/hotspot/cpu/arm/c1_Defs_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -74,6 +74,10 @@ enum { pd_float_saved_as_double = false }; +enum { + pd_two_operand_lir_form = false +}; + #define PATCHED_ADDR (204) #define CARDTABLEBARRIERSET_POST_BARRIER_HELPER diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp index d6085b13e42..1e17d18b246 100644 --- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp @@ -25,6 +25,8 @@ #include "precompiled.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" @@ -62,6 +64,10 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by // if this method contains a methodHandle call site raw_push(FP, LR); sub_slow(SP, SP, frame_size_in_bytes); + + // Insert nmethod entry barrier into frame. + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(this); } void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) { diff --git a/src/hotspot/cpu/arm/c1_globals_arm.hpp b/src/hotspot/cpu/arm/c1_globals_arm.hpp index 55917decc30..d22d39d6369 100644 --- a/src/hotspot/cpu/arm/c1_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c1_globals_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -61,6 +61,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, true); define_pd_global(bool, CSEArrayLength, true); -define_pd_global(bool, TwoOperandLIRForm, false); #endif // CPU_ARM_C1_GLOBALS_ARM_HPP diff --git a/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp b/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp index c166ca72254..f79a22751c1 100644 --- a/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp +++ b/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/arm/downcallLinker_arm.cpp b/src/hotspot/cpu/arm/downcallLinker_arm.cpp index af69f2a58a6..37b6f43ac14 100644 --- a/src/hotspot/cpu/arm/downcallLinker_arm.cpp +++ b/src/hotspot/cpu/arm/downcallLinker_arm.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/arm/foreignGlobals_arm.cpp b/src/hotspot/cpu/arm/foreignGlobals_arm.cpp index 918e89f3ee6..5438cbe5cd6 100644 --- a/src/hotspot/cpu/arm/foreignGlobals_arm.cpp +++ b/src/hotspot/cpu/arm/foreignGlobals_arm.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,24 +34,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp index e521cb9a75e..e9d1a0056b7 100644 --- a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp @@ -23,10 +23,13 @@ */ #include "precompiled.hpp" +#include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" #include "runtime/javaThread.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm-> @@ -195,3 +198,47 @@ void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, RegisterOrC // Unborrow the Rthread __ sub(Rthread, Ralloc, in_bytes(JavaThread::allocated_bytes_offset())); } + +void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { + + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + + Register tmp0 = Rtemp; + Register tmp1 = R5; // must be callee-save register + + if (bs_nm == NULL) { + return; + } + + // The are no GCs that require memory barrier on arm32 now +#ifdef ASSERT + NMethodPatchingType patching_type = nmethod_patching_type(); + assert(patching_type == NMethodPatchingType::stw_instruction_and_data_patch, "Unsupported patching type"); +#endif + + Label skip, guard; + Address thread_disarmed_addr(Rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); + + __ block_comment("nmethod_barrier begin"); + __ ldr_label(tmp0, guard); + + // No memory barrier here + __ ldr(tmp1, thread_disarmed_addr); + __ cmp(tmp0, tmp1); + __ b(skip, eq); + + __ mov_address(tmp0, StubRoutines::Arm::method_entry_barrier()); + __ call(tmp0); + __ b(skip); + + __ bind(guard); + + // nmethod guard value. Skipped over in common case. + // + // Put a debug value to make any offsets skew + // clearly visible in coredump + __ emit_int32(0xDEADBEAF); + + __ bind(skip); + __ block_comment("nmethod_barrier end"); +} diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp index 6f100677a8c..37e0c6525f3 100644 --- a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp @@ -29,6 +29,10 @@ #include "memory/allocation.hpp" #include "oops/access.hpp" +enum class NMethodPatchingType { + stw_instruction_and_data_patch, +}; + class BarrierSetAssembler: public CHeapObj { private: void incr_allocated_bytes(MacroAssembler* masm, @@ -56,6 +60,8 @@ class BarrierSetAssembler: public CHeapObj { ); virtual void barrier_stubs_init() {} + virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::stw_instruction_and_data_patch; } + virtual void nmethod_entry_barrier(MacroAssembler* masm); }; #endif // CPU_ARM_GC_SHARED_BARRIERSETASSEMBLER_ARM_HPP diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp index a0361ddc2f4..ed15cc5ebcf 100644 --- a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp @@ -23,18 +23,115 @@ */ #include "precompiled.hpp" +#include "code/nativeInst.hpp" +#include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/barrierSetNMethod.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/javaThread.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/registerMap.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" +// The constant below reflects the size of the barrier +// in barrierSetAssembler_arm.cpp +static const int entry_barrier_bytes = 9 * NativeInstruction::size(); + +class NativeNMethodBarrier: public NativeInstruction { + address instruction_address() const { return addr_at(0); } + + int *guard_addr() const { + // Last instruction in a barrier + return reinterpret_cast(instruction_address() + entry_barrier_bytes - wordSize); + } + +public: + int get_value() { + return Atomic::load_acquire(guard_addr()); + } + + void set_value(int value) { + Atomic::release_store(guard_addr(), value); + } + + void verify() const; +}; + +// Check the first instruction of the nmethod entry barrier +// to make sure that the offsets are not skewed. +void NativeNMethodBarrier::verify() const { + NativeInstruction *ni = (NativeInstruction *) instruction_address(); + if (!ni->is_ldr()) { + uint32_t *addr = (uint32_t *) ni; + tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", (intptr_t) addr, (uint32_t) *addr); + fatal("not an ldr instruction."); + } +} + +static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { + address barrier_address = nm->code_begin() + nm->frame_complete_offset() - entry_barrier_bytes; + NativeNMethodBarrier* barrier = reinterpret_cast(barrier_address); + debug_only(barrier->verify()); + return barrier; +} + +/* We're called from an nmethod when we need to deoptimize it. We do + this by throwing away the nmethod's frame and jumping to the + ic_miss stub. This looks like there has been an IC miss at the + entry of the nmethod, so we resolve the call, which will fall back + to the interpreter if the nmethod has been unloaded. */ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { - ShouldNotReachHere(); + + typedef struct { + intptr_t *sp; intptr_t *fp; address lr; address pc; + } frame_pointers_t; + + frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5); + + JavaThread *thread = JavaThread::current(); + RegisterMap reg_map(thread, + RegisterMap::UpdateMap::skip, + RegisterMap::ProcessFrames::include, + RegisterMap::WalkContinuation::skip); + frame frame = thread->last_frame(); + + assert(frame.is_compiled_frame() || frame.is_native_frame(), "must be"); + assert(frame.cb() == nm, "must be"); + frame = frame.sender(®_map); + + LogTarget(Trace, nmethod, barrier) out; + if (out.is_enabled()) { + ResourceMark mark; + log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", + nm->method()->name_and_sig_as_C_string(), + nm, *(address *) return_address_ptr, nm->is_osr_method(), thread, + thread->name(), frame.sp(), nm->verified_entry_point()); + } + + new_frame->sp = frame.sp(); + new_frame->fp = frame.fp(); + new_frame->lr = frame.pc(); + new_frame->pc = SharedRuntime::get_handle_wrong_method_stub(); } -void BarrierSetNMethod::disarm(nmethod* nm) { - ShouldNotReachHere(); +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { + if (!supports_entry_barrier(nm)) { + return; + } + + // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. + // Symmetric "LDR; DMB ISHLD" is in the nmethod barrier. + NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); + barrier->set_value(value); } -bool BarrierSetNMethod::is_armed(nmethod* nm) { - ShouldNotReachHere(); - return false; +int BarrierSetNMethod::guard_value(nmethod* nm) { + if (!supports_entry_barrier(nm)) { + return disarmed_guard_value(); + } + + NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); + return barrier->get_value(); } diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 1c7ae0f54f3..8744ac6dedd 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -1643,7 +1643,7 @@ void MacroAssembler::store_heap_oop_null(Address obj, Register new_val, Register void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); @@ -1655,7 +1655,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp index 73e2f2c0d17..50b56bfe79a 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -587,9 +587,23 @@ class MacroAssembler: public Assembler { AbstractAssembler::emit_address((address)L.data()); } + void ldr_label(Register rd, Label& L) { + ldr(rd, Address(PC, target(L) - pc() - 8)); + } + void resolve_oop_handle(Register result); void load_mirror(Register mirror, Register method, Register tmp); + void enter() { + raw_push(FP, LR); + mov(FP, SP); + } + + void leave() { + mov(SP, FP); + raw_pop(FP, LR); + } + #define ARM_INSTR_1(common_mnemonic, arm32_mnemonic, arg_type) \ void common_mnemonic(arg_type arg) { \ arm32_mnemonic(arg); \ diff --git a/src/hotspot/cpu/arm/matcher_arm.hpp b/src/hotspot/cpu/arm/matcher_arm.hpp index 3959d61e71c..1e8f7683e76 100644 --- a/src/hotspot/cpu/arm/matcher_arm.hpp +++ b/src/hotspot/cpu/arm/matcher_arm.hpp @@ -155,6 +155,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = false; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index 0c9e157c553..62419a1ddf5 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -77,9 +77,12 @@ class RawNativeInstruction { address instruction_address() const { return addr_at(0); } address next_raw_instruction_address() const { return addr_at(instruction_size); } + static int size() { return instruction_size; } + static RawNativeInstruction* at(address address) { return (RawNativeInstruction*)address; } + RawNativeInstruction* next_raw() const { return at(next_raw_instruction_address()); } diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index ab0e79d95c1..56dcc8a1903 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -28,6 +28,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" +#include "gc/shared/barrierSetAssembler.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -873,6 +874,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ mov(FP, SP); __ sub_slow(SP, SP, stack_size - 2*wordSize); + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + assert(bs != NULL, "Sanity"); + bs->nmethod_entry_barrier(masm); + int frame_complete = __ pc() - start; OopMapSet* oop_maps = new OopMapSet(); diff --git a/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp b/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp index b3c2714037c..218f5841181 100644 --- a/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp +++ b/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/arm/stubGenerator_arm.cpp b/src/hotspot/cpu/arm/stubGenerator_arm.cpp index 85227dbb8e8..d5204915619 100644 --- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp @@ -27,6 +27,7 @@ #include "compiler/oopMap.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_arm.hpp" @@ -2905,6 +2906,53 @@ class StubGenerator: public StubCodeGenerator { } + address generate_method_entry_barrier() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier"); + + Label deoptimize_label; + + address start = __ pc(); + + // No need to save PC on Arm + __ set_last_Java_frame(SP, FP, false, Rtemp); + + __ enter(); + + __ add(Rtemp, SP, wordSize); // Rtemp points to the saved lr + __ sub(SP, SP, 4 * wordSize); // four words for the returned {sp, fp, lr, pc} + + const RegisterSet saved_regs = RegisterSet(R0, R10); + __ push(saved_regs); + __ fpush(FloatRegisterSet(D0, 16)); + + __ mov(c_rarg0, Rtemp); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier), c_rarg0); + + __ reset_last_Java_frame(Rtemp); + + __ mov(Rtemp, R0); + + __ fpop(FloatRegisterSet(D0, 16)); + __ pop(saved_regs); + + __ cbnz(Rtemp, deoptimize_label); + + __ leave(); + __ bx(LR); + + __ BIND(deoptimize_label); + + __ ldr(Rtemp, Address(SP, 0)); + __ ldr(FP, Address(SP, wordSize)); + __ ldr(LR, Address(SP, wordSize * 2)); + __ ldr(R5, Address(SP, wordSize * 3)); + __ mov(SP, Rtemp); + __ bx(R5); + + return start; + } + #define COMPILE_CRYPTO #include "stubRoutinesCrypto_arm.cpp" @@ -3097,6 +3145,11 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm != NULL) { + StubRoutines::Arm::_method_entry_barrier = generate_method_entry_barrier(); + } + #ifdef COMPILE_CRYPTO // generate AES intrinsics code if (UseAESIntrinsics) { diff --git a/src/hotspot/cpu/arm/stubRoutines_arm.cpp b/src/hotspot/cpu/arm/stubRoutines_arm.cpp index 6ae6d1fe8d1..98280862e98 100644 --- a/src/hotspot/cpu/arm/stubRoutines_arm.cpp +++ b/src/hotspot/cpu/arm/stubRoutines_arm.cpp @@ -33,3 +33,5 @@ address StubRoutines::Arm::_partial_subtype_check = NULL; address StubRoutines::_atomic_load_long_entry = NULL; address StubRoutines::_atomic_store_long_entry = NULL; + +address StubRoutines::Arm::_method_entry_barrier = NULL; diff --git a/src/hotspot/cpu/arm/stubRoutines_arm.hpp b/src/hotspot/cpu/arm/stubRoutines_arm.hpp index c21c08f3e54..2a46e254ee2 100644 --- a/src/hotspot/cpu/arm/stubRoutines_arm.hpp +++ b/src/hotspot/cpu/arm/stubRoutines_arm.hpp @@ -42,11 +42,13 @@ class Arm { static address _idiv_irem_entry; static address _partial_subtype_check; + static address _method_entry_barrier; public: static address idiv_irem_entry() { return _idiv_irem_entry; } static address partial_subtype_check() { return _partial_subtype_check; } + static address method_entry_barrier() { return _method_entry_barrier; } }; static bool returns_to_call_stub(address return_pc) { diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java b/src/hotspot/cpu/arm/vmstorage_arm.hpp similarity index 52% rename from test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java rename to src/hotspot/cpu/arm/vmstorage_arm.hpp index 640000a8efc..fda9ceac0a6 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java +++ b/src/hotspot/cpu/arm/vmstorage_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -21,29 +21,32 @@ * questions. */ -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; +#ifndef CPU_ARM_VMSTORAGE_ARM_INLINE_HPP +#define CPU_ARM_VMSTORAGE_ARM_INLINE_HPP -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; +#include -/* See TckDriver.java for more information */ -public class BodySubscribersDiscarding - extends FlowSubscriberBlackboxVerification> { +#include "asm/register.hpp" - public BodySubscribersDiscarding() { - super(new TestEnvironment(450L)); - } +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.discarding(); - } +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); } + +#endif // CPU_ARM_VMSTORAGE_ARM_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/ppc/assembler_ppc.hpp b/src/hotspot/cpu/ppc/assembler_ppc.hpp index d32f2cbee36..7ea6d8e5876 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp @@ -95,7 +95,7 @@ class AddressLiteral { protected: // creation - AddressLiteral() : _address(NULL), _rspec(NULL) {} + AddressLiteral() : _address(NULL), _rspec() {} public: AddressLiteral(address addr, RelocationHolder const& rspec) diff --git a/src/hotspot/cpu/ppc/c1_Defs_ppc.hpp b/src/hotspot/cpu/ppc/c1_Defs_ppc.hpp index 01d4ba39092..0d18d889da1 100644 --- a/src/hotspot/cpu/ppc/c1_Defs_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_Defs_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -73,4 +73,8 @@ enum { pd_float_saved_as_double = true }; +enum { + pd_two_operand_lir_form = false +}; + #endif // CPU_PPC_C1_DEFS_PPC_HPP diff --git a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp index af6db7555dd..23604b5c083 100644 --- a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -61,6 +61,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, false); define_pd_global(bool, CSEArrayLength, true); -define_pd_global(bool, TwoOperandLIRForm, false); #endif // CPU_PPC_C1_GLOBALS_PPC_HPP diff --git a/src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp b/src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp similarity index 80% rename from src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp rename to src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp index b65b91df1b8..f99f9e978cf 100644 --- a/src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -24,19 +24,22 @@ */ #include "precompiled.hpp" -#include "macroAssembler_ppc.inline.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 56; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); - __ bind(entry->_stub_label); + __ bind(entry()); // Using pc relative address computation. { Label next_pc; @@ -45,7 +48,7 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP } int current_offset = __ offset(); // Code size should not depend on offset: see _stub_size computation in output.cpp - __ load_const32(R12, entry->_safepoint_offset - current_offset); + __ load_const32(R12, _safepoint_offset - current_offset); __ mflr(R0); __ add(R12, R12, R0); __ std(R12, in_bytes(JavaThread::saved_exception_pc_offset()), R16_thread); diff --git a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp index 86afc73e286..13679cf6669 100644 --- a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp @@ -30,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp b/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp index 53eb53ec7cb..b685023656d 100644 --- a/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp +++ b/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp @@ -35,24 +35,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index 219e167ef60..9e871481090 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -163,7 +163,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t __ load_const32(tmp, 0 /* Value is patched */); // 2 instructions // Low order half of 64 bit value is currently used. - __ ld(R0, in_bytes(bs_nm->thread_disarmed_offset()), R16_thread); + __ ld(R0, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), R16_thread); __ cmpw(CCR0, R0, tmp); __ bnectrl(CCR0); diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp index 698953671f1..d1d0e5ab024 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp @@ -118,29 +118,20 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { // Thus, there's nothing to do here. } -void BarrierSetNMethod::disarm(nmethod* nm) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { if (!supports_entry_barrier(nm)) { return; } NativeNMethodBarrier* barrier = get_nmethod_barrier(nm); - barrier->release_set_guard_value(disarmed_value()); + barrier->release_set_guard_value(value); } -void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { +int BarrierSetNMethod::guard_value(nmethod* nm) { if (!supports_entry_barrier(nm)) { - return; - } - - NativeNMethodBarrier* barrier = get_nmethod_barrier(nm); - barrier->release_set_guard_value(arm_value); -} - -bool BarrierSetNMethod::is_armed(nmethod* nm) { - if (!supports_entry_barrier(nm)) { - return false; + return disarmed_guard_value(); } NativeNMethodBarrier* barrier = get_nmethod_barrier(nm); - return barrier->get_guard_value() != disarmed_value(); + return barrier->get_guard_value(); } diff --git a/src/hotspot/cpu/ppc/globals_ppc.hpp b/src/hotspot/cpu/ppc/globals_ppc.hpp index 44b321635e1..527e5f5b4da 100644 --- a/src/hotspot/cpu/ppc/globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/globals_ppc.hpp @@ -54,7 +54,7 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES); define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES); define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES); -define_pd_global(bool, VMContinuations, true); +define_pd_global(bool, VMContinuations, AIX_ONLY(false) NOT_AIX(true)); // Use large code-entry alignment. define_pd_global(uintx, CodeCacheSegmentSize, 128); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp index 5be76916b21..d4a08310dd9 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp @@ -357,7 +357,7 @@ inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorat ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bool as_raw = (decorators & AS_RAW) != 0; - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, base, ind_or_offs, val, @@ -377,7 +377,7 @@ inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorato assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index 05e06a21b1c..f78cb2d7803 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -164,6 +164,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 296bf160089..17d0dfc4e34 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2023, 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. // @@ -982,6 +982,7 @@ source_hpp %{ source %{ +#include "opto/c2_CodeStubs.hpp" #include "oops/klass.inline.hpp" void PhaseOutput::pd_perform_mach_node_analysis() { @@ -1616,7 +1617,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!UseSIGTRAP && !C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); __ relocate(relocInfo::poll_return_type); } __ safepoint_poll(*code_stub, temp, true /* at_return */, true /* in_nmethod */); @@ -6534,6 +6537,7 @@ instruct storeNKlass(memory dst, iRegN_P2N src) %{ // Store Pointer instruct storeP(memoryAlg4 dst, iRegPsrc src) %{ match(Set dst (StoreP dst src)); + predicate(n->as_Store()->barrier_data() == 0); ins_cost(MEMORY_REF_COST); format %{ "STD $src, $dst \t// ptr" %} @@ -14374,6 +14378,12 @@ instruct safePoint_poll(iRegPdst poll) %{ // Call Java Static Instruction +source %{ + +#include "runtime/continuation.hpp" + +%} + // Schedulable version of call static node. instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); diff --git a/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp b/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp index 06b0f045f1c..e4489660f46 100644 --- a/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp @@ -80,12 +80,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(ijava_idx(esp)) + 1 - frame::metadata_words; // On PPC esp points to the next free slot } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp similarity index 52% rename from test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java rename to src/hotspot/cpu/ppc/vmstorage_ppc.hpp index 18991f63ddb..46efafebe0c 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java +++ b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -21,29 +21,32 @@ * questions. */ -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; +#ifndef CPU_PPC_VMSTORAGE_PPC_INLINE_HPP +#define CPU_PPC_VMSTORAGE_PPC_INLINE_HPP -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; +#include -/* See TckDriver.java for more information */ -public class BodySubscribersOfByteArray - extends FlowSubscriberBlackboxVerification> { +#include "asm/register.hpp" - public BodySubscribersOfByteArray() { - super(new TestEnvironment(450L)); - } +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofByteArray(); - } +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); } + +#endif // CPU_PPC_VMSTORAGE_PPC_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp index 2fb75c802cf..6a581a4d081 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp @@ -40,8 +40,20 @@ int AbstractAssembler::code_fill_byte() { return 0; } -Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) { - _target = target; +#ifdef ASSERT + +void Address::assert_is_literal() const { + assert(_mode == literal, "addressing mode is non-literal: %d", _mode); +} + +void Address::assert_is_nonliteral() const { + assert(_mode != literal, "unexpected literal addressing mode"); + assert(_mode != no_mode, "unexpected no_mode addressing mode"); +} + +#endif // ASSERT + +static RelocationHolder address_relocation(address target, relocInfo::relocType rtype) { switch (rtype) { case relocInfo::oop_type: case relocInfo::metadata_type: @@ -49,30 +61,29 @@ Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _of // but in cases like icBuffer they are literals in the code stream that // we don't have a section for. We use none so that we get a literal address // which is always patchable. - break; + return RelocationHolder::none; case relocInfo::external_word_type: - _rspec = external_word_Relocation::spec(target); - break; + return external_word_Relocation::spec(target); case relocInfo::internal_word_type: - _rspec = internal_word_Relocation::spec(target); - break; + return internal_word_Relocation::spec(target); case relocInfo::opt_virtual_call_type: - _rspec = opt_virtual_call_Relocation::spec(); - break; + return opt_virtual_call_Relocation::spec(); case relocInfo::static_call_type: - _rspec = static_call_Relocation::spec(); - break; + return static_call_Relocation::spec(); case relocInfo::runtime_call_type: - _rspec = runtime_call_Relocation::spec(); - break; + return runtime_call_Relocation::spec(); case relocInfo::poll_type: case relocInfo::poll_return_type: - _rspec = Relocation::spec_simple(rtype); - break; + return Relocation::spec_simple(rtype); case relocInfo::none: - _rspec = RelocationHolder::none; - break; + return RelocationHolder::none; default: ShouldNotReachHere(); + return RelocationHolder::none; } } + +Address::Address(address target, relocInfo::relocType rtype) : + _mode(literal), + _literal(target, address_relocation(target, rtype)) +{} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index b381f727a83..b39366646c8 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -30,6 +30,10 @@ #include "asm/register.hpp" #include "assembler_riscv.inline.hpp" #include "metaprogramming/enableIf.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" +#include #define XLEN 64 @@ -153,62 +157,128 @@ const FloatRegister g_FPArgReg[Argument::n_float_register_parameters_c] = { class Address { public: - enum mode { no_mode, base_plus_offset, pcrel, literal }; + enum mode { no_mode, base_plus_offset, literal }; private: - Register _base; - Register _index; - int64_t _offset; - enum mode _mode; + struct Nonliteral { + Nonliteral(Register base, Register index, int64_t offset) + : _base(base), _index(index), _offset(offset) {} + Register _base; + Register _index; + int64_t _offset; + }; + + struct Literal { + Literal(address target, const RelocationHolder& rspec) + : _target(target), _rspec(rspec) {} + // If the target is far we'll need to load the ea of this to a + // register to reach it. Otherwise if near we can do PC-relative + // addressing. + address _target; + + RelocationHolder _rspec; + }; + + void assert_is_nonliteral() const NOT_DEBUG_RETURN; + void assert_is_literal() const NOT_DEBUG_RETURN; - RelocationHolder _rspec; + // Discriminated union, based on _mode. + // - no_mode: uses dummy _nonliteral, for ease of copying. + // - literal: only _literal is used. + // - others: only _nonliteral is used. + enum mode _mode; + union { + Nonliteral _nonliteral; + Literal _literal; + }; - // If the target is far we'll need to load the ea of this to a - // register to reach it. Otherwise if near we can do PC-relative - // addressing. - address _target; + // Helper for copy constructor and assignment operator. + // Copy mode-relevant part of a into this. + void copy_data(const Address& a) { + assert(_mode == a._mode, "precondition"); + if (_mode == literal) { + new (&_literal) Literal(a._literal); + } else { + // non-literal mode or no_mode. + new (&_nonliteral) Nonliteral(a._nonliteral); + } + } public: - Address() - : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } + // no_mode initializes _nonliteral for ease of copying. + Address() : + _mode(no_mode), + _nonliteral(noreg, noreg, 0) + {} - Address(Register r) - : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } + Address(Register r) : + _mode(base_plus_offset), + _nonliteral(r, noreg, 0) + {} template::value)> - Address(Register r, T o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) {} + Address(Register r, T o) : + _mode(base_plus_offset), + _nonliteral(r, noreg, o) + {} - Address(Register r, ByteSize disp) - : Address(r, in_bytes(disp)) {} + Address(Register r, ByteSize disp) : Address(r, in_bytes(disp)) {} - Address(address target, RelocationHolder const& rspec) - : _base(noreg), - _index(noreg), - _offset(0), - _mode(literal), - _rspec(rspec), - _target(target) { } + Address(address target, const RelocationHolder& rspec) : + _mode(literal), + _literal(target, rspec) + {} Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type); + Address(const Address& a) : _mode(a._mode) { copy_data(a); } + + // Verify the value is trivially destructible regardless of mode, so our + // destructor can also be trivial, and so our assignment operator doesn't + // need to destruct the old value before copying over it. + static_assert(std::is_trivially_destructible::value, "must be"); + static_assert(std::is_trivially_destructible::value, "must be"); + + Address& operator=(const Address& a) { + _mode = a._mode; + copy_data(a); + return *this; + } + + ~Address() = default; + const Register base() const { - guarantee((_mode == base_plus_offset | _mode == pcrel | _mode == literal), "wrong mode"); - return _base; + assert_is_nonliteral(); + return _nonliteral._base; } + long offset() const { - return _offset; + assert_is_nonliteral(); + return _nonliteral._offset; } + Register index() const { - return _index; + assert_is_nonliteral(); + return _nonliteral._index; } + mode getMode() const { return _mode; } - bool uses(Register reg) const { return _base == reg; } - const address target() const { return _target; } - const RelocationHolder& rspec() const { return _rspec; } + bool uses(Register reg) const { + return base() == reg; + } + + const address target() const { + assert_is_literal(); + return _literal._target; + } + + const RelocationHolder& rspec() const { + assert_is_literal(); + return _literal._rspec; + } }; // Convenience classes @@ -728,6 +798,8 @@ enum operand_size { int8, int16, int32, uint32, int64 }; INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101); INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000); INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001); + INSN(fcvt_s_h, 0b1010011, 0b00010, 0b0100000); + INSN(fcvt_h_s, 0b1010011, 0b00000, 0b0100010); #undef INSN // Immediate Instruction @@ -984,6 +1056,7 @@ enum operand_size { int8, int16, int32, uint32, int64 }; INSN(fmv_w_x, 0b1010011, 0b000, 0b00000, 0b1111000); INSN(fmv_d_x, 0b1010011, 0b000, 0b00000, 0b1111001); + INSN(fmv_h_x, 0b1010011, 0b000, 0b00000, 0b1111010); #undef INSN @@ -1004,6 +1077,7 @@ enum operand_size { int8, int16, int32, uint32, int64 }; INSN(fclass_d, 0b1010011, 0b001, 0b00000, 0b1110001); INSN(fmv_x_w, 0b1010011, 0b000, 0b00000, 0b1110000); INSN(fmv_x_d, 0b1010011, 0b000, 0b00000, 0b1110001); + INSN(fmv_x_h, 0b1010011, 0b000, 0b00000, 0b1110010); #undef INSN @@ -1670,7 +1744,7 @@ enum Nf { // ==================================== // RISC-V Bit-Manipulation Extension -// Currently only support Zba and Zbb bitmanip extensions. +// Currently only support Zba, Zbb and Zbs bitmanip extensions. // ==================================== #define INSN(NAME, op, funct3, funct7) \ void NAME(Register Rd, Register Rs1, Register Rs2) { \ @@ -1745,6 +1819,7 @@ enum Nf { INSN(rori, 0b0010011, 0b101, 0b011000); INSN(slli_uw, 0b0011011, 0b001, 0b000010); + INSN(bexti, 0b0010011, 0b101, 0b010010); #undef INSN diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp index b241a753050..197216d6eca 100644 --- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp @@ -43,7 +43,9 @@ void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset()); __ relocate(safepoint_pc.rspec(), [&] { - __ la(t0, safepoint_pc.target()); + int32_t offset; + __ la_patchable(t0, safepoint_pc.target(), offset); + __ addi(t0, t0, offset); }); __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); diff --git a/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp index 9e132a52699..967bfc9d539 100644 --- a/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -81,4 +81,8 @@ enum { pd_float_saved_as_double = false }; +enum { + pd_two_operand_lir_form = false +}; + #endif // CPU_RISCV_C1_DEFS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp index fe46f7b21c8..311405dbc2b 100644 --- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -60,6 +60,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, true ); define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, false); #endif // CPU_RISCV_C1_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp similarity index 59% rename from src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp rename to src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp index d22a6a75843..4ddd6f3c2c3 100644 --- a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,25 +24,52 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_CodeStubs.hpp" +#include "opto/c2_MacroAssembler.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 13 * 4; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(__ pc() - __ offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(__ pc() - __ offset() + _safepoint_offset); __ relocate(safepoint_pc.rspec(), [&] { - __ la(t0, safepoint_pc.target()); + int32_t offset; + __ la_patchable(t0, safepoint_pc.target(), offset); + __ addi(t0, t0, offset); }); __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); __ far_jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + // 4 bytes for alignment + return 8 * 4 + 4; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + + int32_t offset = 0; + __ movptr(t0, StubRoutines::riscv::method_entry_barrier(), offset); + __ jalr(ra, t0, offset); + __ j(continuation()); + + // make guard value 4-byte aligned so that it can be accessed by atomic instructions on RISC-V + __ align(4); + __ bind(guard()); + __ relocate(entry_guard_Relocation::spec()); + __ emit_int32(0); // nmethod guard value +} + #undef __ diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index e4c892280d6..09c4274a84b 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -243,37 +243,6 @@ void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - IncompressibleRegion ir(this); // Fixed length: see C2_MacroAssembler::entry_barrier_stub_size() - - // make guard value 4-byte aligned so that it can be accessed by atomic instructions on riscv - int alignment_bytes = align(4); - - bind(stub->slow_path()); - - int32_t offset = 0; - movptr(t0, StubRoutines::riscv::method_entry_barrier(), offset); - jalr(ra, t0, offset); - j(stub->continuation()); - - bind(stub->guard()); - relocate(entry_guard_Relocation::spec()); - assert_alignment(pc()); - emit_int32(0); // nmethod guard value - // make sure the stub with a fixed code size - if (alignment_bytes == 2) { - assert(UseRVC, "bad alignment"); - c_nop(); - } else { - assert(alignment_bytes == 0, "bad alignment"); - nop(); - } -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 8 * 4 + 4; // 4 bytes for alignment margin -} - // Search for needle in haystack and return index or -1 // x10: result // x11: haystack @@ -593,7 +562,12 @@ void C2_MacroAssembler::string_indexof(Register haystack, Register needle, stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); } - trampoline_call(stub); + address call = trampoline_call(stub); + if (call == nullptr) { + DEBUG_ONLY(reset_labels(LINEARSEARCH, DONE, NOMATCH)); + ciEnv::current()->record_failure("CodeCache is full"); + return; + } j(DONE); bind(NOMATCH); @@ -996,7 +970,12 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, ShouldNotReachHere(); } assert(stub.target() != NULL, "compare_long_string stub has not been generated"); - trampoline_call(stub); + address call = trampoline_call(stub); + if (call == nullptr) { + DEBUG_ONLY(reset_labels(DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, SHORT_LOOP_START)); + ciEnv::current()->record_failure("CodeCache is full"); + return; + } j(DONE); bind(SHORT_STRING); @@ -1726,4 +1705,4 @@ void C2_MacroAssembler::rvv_reduce_integral(Register dst, VectorRegister tmp, } vmv_x_s(dst, tmp); -} \ No newline at end of file +} diff --git a/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp b/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp index b4746649f19..eedaff87b2c 100644 --- a/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp +++ b/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp @@ -53,7 +53,14 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline bool p_succeeded = true; auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) { masm.set_code_section(cb->stubs()); - masm.align(wordSize, NativeCallTrampolineStub::data_offset); + if (!is_aligned(masm.offset() + NativeCallTrampolineStub::data_offset, wordSize)) { + if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + p_succeeded = false; + return p_succeeded; + } + masm.align(wordSize, NativeCallTrampolineStub::data_offset); + } LinkedListIterator it(offsets.head()); int offset = *it.next(); diff --git a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp index 9f69f681ba3..7863cbe6415 100644 --- a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp @@ -199,11 +199,6 @@ inline void ThawBase::prefetch_chunk_pd(void* start, int size) { Prefetch::read(start, size - 64); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - 2) = fp; -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { // Fast path depends on !PreserveFramePointer. See can_thaw_fast(). diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index 9bd1f8002db..7d757e75180 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -31,9 +31,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp b/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp index a239ed40df3..aefbb56a491 100644 --- a/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp +++ b/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp @@ -35,25 +35,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } - diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp index 4b102b576fa..60b5ffa41f8 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -220,7 +220,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo // instruction patching is synchronized with global icache_flush() by // the write hart on riscv. So here we can do a plain conditional // branch with no fencing. - Address thread_disarmed_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset())); + Address thread_disarmed_addr(xthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); __ lwu(t1, thread_disarmed_addr); break; } @@ -245,7 +245,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo __ slli(t1, t1, 32); __ orr(t0, t0, t1); // Compare the global values with the thread-local values - Address thread_disarmed_and_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset())); + Address thread_disarmed_and_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); __ ld(t1, thread_disarmed_and_epoch_addr); break; } diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp index 33126326a97..b8e61ff3a1d 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp @@ -171,32 +171,12 @@ static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { return barrier; } -void BarrierSetNMethod::disarm(nmethod* nm) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { if (!supports_entry_barrier(nm)) { return; } - // The patching epoch is incremented before the nmethod is disarmed. Disarming - // is performed with a release store. In the nmethod entry barrier, the values - // are read in the opposite order, such that the load of the nmethod guard - // acquires the patching epoch. This way, the guard is guaranteed to block - // entries to the nmethod, util it has safely published the requirement for - // further fencing by mutators, before they are allowed to enter. - BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->increment_patching_epoch(); - - // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. - // Symmetric "LD; FENCE IR, IR" is in the nmethod barrier. - NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - barrier->set_value(nm, disarmed_value()); -} - -void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { - if (!supports_entry_barrier(nm)) { - return; - } - - if (arm_value == disarmed_value()) { + if (value == disarmed_guard_value()) { // The patching epoch is incremented before the nmethod is disarmed. Disarming // is performed with a release store. In the nmethod entry barrier, the values // are read in the opposite order, such that the load of the nmethod guard @@ -208,14 +188,14 @@ void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { } NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - barrier->set_value(nm, arm_value); + barrier->set_value(nm, value); } -bool BarrierSetNMethod::is_armed(nmethod* nm) { +int BarrierSetNMethod::guard_value(nmethod* nm) { if (!supports_entry_barrier(nm)) { - return false; + return disarmed_guard_value(); } NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); - return barrier->get_value(nm) != disarmed_value(); + return barrier->get_value(nm); } diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 962ba7f8593..580ded4b093 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -102,6 +102,8 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseRVV, false, EXPERIMENTAL, "Use RVV instructions") \ product(bool, UseZba, false, EXPERIMENTAL, "Use Zba instructions") \ product(bool, UseZbb, false, EXPERIMENTAL, "Use Zbb instructions") \ + product(bool, UseZbs, false, EXPERIMENTAL, "Use Zbs instructions") \ + product(bool, UseZfhmin, false, EXPERIMENTAL, "Use Zfhmin instructions") \ product(bool, UseZic64b, false, EXPERIMENTAL, "Use Zic64b instructions") \ product(bool, UseZicbom, false, EXPERIMENTAL, "Use Zicbom instructions") \ product(bool, UseZicbop, false, EXPERIMENTAL, "Use Zicbop instructions") \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 779e7912b43..ebdb5f04dce 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -210,6 +210,7 @@ void MacroAssembler::post_call_nop() { } relocate(post_call_nop_Relocation::spec(), [&] { nop(); + li32(zr, 0); }); } @@ -407,10 +408,13 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file, push_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); mv(c_rarg0, reg); // c_rarg0 : x10 - // The length of the instruction sequence emitted should be independent - // of the value of the local char buffer address so that the size of mach - // nodes for scratch emit and normal emit matches. - movptr(t0, (address)b); + { + // The length of the instruction sequence emitted should not depend + // on the address of the char buffer so that the size of mach nodes for + // scratch emit and normal emit matches. + IncompressibleRegion ir(this); // Fixed length + movptr(t0, (address) b); + } // call indirectly to solve generation ordering problem ExternalAddress target(StubRoutines::verify_oop_subroutine_entry_address()); @@ -449,10 +453,13 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* f ld(x10, addr); } - // The length of the instruction sequence emitted should be independent - // of the value of the local char buffer address so that the size of mach - // nodes for scratch emit and normal emit matches. - movptr(t0, (address)b); + { + // The length of the instruction sequence emitted should not depend + // on the address of the char buffer so that the size of mach nodes for + // scratch emit and normal emit matches. + IncompressibleRegion ir(this); // Fixed length + movptr(t0, (address) b); + } // call indirectly to solve generation ordering problem ExternalAddress target(StubRoutines::verify_oop_subroutine_entry_address()); @@ -1383,7 +1390,7 @@ static int patch_imm_in_li64(address branch, address target) { return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; } -static int patch_imm_in_li32(address branch, int32_t target) { +int MacroAssembler::patch_imm_in_li32(address branch, int32_t target) { const int LI32_INSTRUCTIONS_NUM = 2; // lui + addiw int64_t upper = (intptr_t)target; int32_t lower = (((int32_t)target) << 20) >> 20; @@ -1447,7 +1454,7 @@ static address get_target_of_li64(address insn_addr) { return (address)target_address; } -static address get_target_of_li32(address insn_addr) { +address MacroAssembler::get_target_of_li32(address insn_addr) { assert_cond(insn_addr != NULL); intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 12; // Lui. target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)); // Addiw. @@ -1993,7 +2000,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register tmp2) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2); @@ -2018,7 +2025,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); @@ -3128,6 +3135,9 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, return NULL; // CodeBuffer::expand failed } + // We are always 4-byte aligned here. + assert_alignment(pc()); + // Create a trampoline stub relocation which relates this trampoline stub // with the call instruction at insts_call_instruction_offset in the // instructions code-section. diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 811eef7f8ab..18c0e7057c4 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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. @@ -387,6 +387,9 @@ class MacroAssembler: public Assembler { static int patch_oop(address insn_addr, address o); + static address get_target_of_li32(address insn_addr); + static int patch_imm_in_li32(address branch, int32_t target); + // Return whether code is emitted to a scratch blob. virtual bool in_scratch_emit_size() { return false; @@ -1325,8 +1328,6 @@ class MacroAssembler: public Assembler { jalr(x0, x1, 0); } -private: - #ifdef ASSERT // Template short-hand support to clean-up after a failed call to trampoline // call generation (see trampoline_call() below), when a set of Labels must @@ -1340,6 +1341,9 @@ class MacroAssembler: public Assembler { lbl.reset(); } #endif + +private: + void repne_scan(Register addr, Register value, Register count, Register tmp); // Return true if an address is within the 48-bit RISCV64 address space. diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp index ff93ddf80a4..7d234d42b9b 100644 --- a/src/hotspot/cpu/riscv/matcher_riscv.hpp +++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp @@ -161,6 +161,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = false; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index e7be863660d..d7385f59737 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -444,8 +444,16 @@ void NativePostCallNop::make_deopt() { NativeDeoptInstruction::insert(addr_at(0)); } +int NativePostCallNop::displacement() const { + // Discard the high 32 bits + return (int)(intptr_t)MacroAssembler::get_target_of_li32(addr_at(4)); +} + void NativePostCallNop::patch(jint diff) { - // unsupported for now + assert(diff != 0, "must be"); + assert(is_lui_to_zr_at(addr_at(4)) && is_addiw_to_zr_at(addr_at(8)), "must be"); + + MacroAssembler::patch_imm_in_li32(addr_at(4), diff); } void NativeDeoptInstruction::verify() { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index a6ed27870c4..72a7b62c124 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -78,7 +78,9 @@ class NativeInstruction { static bool is_jump_at(address instr) { assert_cond(instr != NULL); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } static bool is_addi_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } static bool is_addiw_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } + static bool is_addiw_to_zr_at(address instr) { assert_cond(instr != NULL); return is_addiw_at(instr) && extract_rd(instr) == zr; } static bool is_lui_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0110111; } + static bool is_lui_to_zr_at(address instr) { assert_cond(instr != NULL); return is_lui_at(instr) && extract_rd(instr) == zr; } static bool is_slli_shift_at(address instr, uint32_t shift) { assert_cond(instr != NULL); return (extract_opcode(instr) == 0b0010011 && // opcode field @@ -554,10 +556,22 @@ inline NativeMembar *NativeMembar_at(address addr) { return (NativeMembar*)addr; } +// A NativePostCallNop takes the form of three instructions: +// nop; lui zr, hi20; addiw zr, lo12 +// +// The nop is patchable for a deoptimization trap. The lui and addiw +// instructions execute as nops but have a 20/12-bit payload in which we +// can store an offset from the initial nop to the nmethod. class NativePostCallNop: public NativeInstruction { public: - bool check() const { return is_nop(); } - int displacement() const { return 0; } + bool check() const { + // Check for two instructions: nop; lui zr, hi20 + // These instructions only ever appear together in a post-call + // NOP, so it's unnecessary to check that the third instruction is + // an addiw as well. + return is_nop() && is_lui_to_zr_at(addr_at(4)); + } + int displacement() const; void patch(jint diff); void make_deopt(); }; diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index c496754d070..e3c0242cfd7 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. // 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. @@ -1303,7 +1303,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { st->print("ld t0, [guard]\n\t"); st->print("membar LoadLoad\n\t"); - st->print("ld t1, [xthread, #thread_disarmed_offset]\n\t"); + st->print("ld t1, [xthread, #thread_disarmed_guard_value_offset]\n\t"); st->print("beq t0, t1, skip\n\t"); st->print("jalr #nmethod_entry_barrier_stub\n\t"); st->print("j skip\n\t"); @@ -1361,8 +1361,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label* guard = &dummy_guard; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); guard = &stub->guard(); } @@ -1443,7 +1444,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); @@ -1839,6 +1842,10 @@ const bool Matcher::match_rule_supported(int opcode) { case Op_CountTrailingZerosI: case Op_CountTrailingZerosL: return UseZbb; + + case Op_ConvF2HF: + case Op_ConvHF2F: + return UseZfhmin; } return true; // Per default match rules are supported. @@ -2984,6 +2991,14 @@ operand immI_16bits() interface(CONST_INTER); %} +operand immIpowerOf2() %{ + predicate(is_power_of_2((juint)(n->get_int()))); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: low 32-bit mask operand immL_32bits() %{ @@ -5103,6 +5118,7 @@ instruct storeimmL0(immL0 zero, memory mem) instruct storeP(iRegP src, memory mem) %{ match(Set mem (StoreP mem src)); + predicate(n->as_Store()->barrier_data() == 0); ins_cost(STORE_COST); format %{ "sd $src, $mem\t# ptr, #@storeP" %} @@ -5118,6 +5134,7 @@ instruct storeP(iRegP src, memory mem) instruct storeimmP0(immP0 zero, memory mem) %{ match(Set mem (StoreP mem zero)); + predicate(n->as_Store()->barrier_data() == 0); ins_cost(STORE_COST); format %{ "sd zr, $mem\t# ptr, #@storeimmP0" %} @@ -8124,6 +8141,44 @@ instruct convL2F_reg_reg(fRegF dst, iRegL src) %{ ins_pipe(fp_l2f); %} +// float <-> half float + +instruct convHF2F_reg_reg(fRegF dst, iRegINoSp src, fRegF tmp) %{ + predicate(UseZfhmin); + match(Set dst (ConvHF2F src)); + effect(TEMP tmp); + + ins_cost(XFER_COST); + format %{ "fmv.h.x $tmp, $src\t#@convHF2F_reg_reg\n\t" + "fcvt.s.h $dst, $tmp\t#@convHF2F_reg_reg" + %} + + ins_encode %{ + __ fmv_h_x($tmp$$FloatRegister, $src$$Register); + __ fcvt_s_h($dst$$FloatRegister, $tmp$$FloatRegister); + %} + + ins_pipe(fp_i2f); +%} + +instruct convF2HF_reg_reg(iRegINoSp dst, fRegF src, fRegF tmp) %{ + predicate(UseZfhmin); + match(Set dst (ConvF2HF src)); + effect(TEMP tmp); + + ins_cost(XFER_COST); + format %{ "fcvt.h.s $tmp, $src\t#@convF2HF_reg_reg\n\t" + "fmv.x.h $dst, $tmp\t#@convF2HF_reg_reg" + %} + + ins_encode %{ + __ fcvt_h_s($tmp$$FloatRegister, $src$$FloatRegister); + __ fmv_x_h($dst$$Register, $tmp$$FloatRegister); + %} + + ins_pipe(fp_f2i); +%} + // double <-> int instruct convD2I_reg_reg(iRegINoSp dst, fRegD src) %{ diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad index bbebe13f0a8..0d29fc06e00 100644 --- a/src/hotspot/cpu/riscv/riscv_b.ad +++ b/src/hotspot/cpu/riscv/riscv_b.ad @@ -524,4 +524,18 @@ instruct ornL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ %} ins_pipe(ialu_reg_reg); -%} \ No newline at end of file +%} + +// AndI 0b0..010..0 + ConvI2B +instruct convI2Bool_andI_reg_immIpowerOf2(iRegINoSp dst, iRegIorL2I src, immIpowerOf2 mask) %{ + predicate(UseZbs); + match(Set dst (Conv2B (AndI src mask))); + ins_cost(ALU_COST); + + format %{ "bexti $dst, $src, $mask\t#@convI2Bool_andI_reg_immIpowerOf2" %} + ins_encode %{ + __ bexti($dst$$Register, $src$$Register, exact_log2((juint)($mask$$constant))); + %} + + ins_pipe(ialu_reg_reg); +%} diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 1132e46c64a..5cdf49dadb8 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -74,7 +74,6 @@ source %{ case Op_VectorCastL2X: case Op_VectorCastS2X: case Op_VectorInsert: - case Op_VectorLoadConst: case Op_VectorLoadMask: case Op_VectorLoadShuffle: case Op_VectorMaskCmp: @@ -2077,3 +2076,20 @@ instruct vclearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy, ins_pipe(pipe_class_memory); %} + +// Vector Load Const +instruct vloadcon(vReg dst, immI0 src) %{ + match(Set dst (VectorLoadConst src)); + ins_cost(VEC_COST); + format %{ "vloadcon $dst\t# generate iota indices" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli(t0, x0, sew); + __ vid_v(as_VectorRegister($dst$$reg)); + if (is_floating_point_type(bt)) { + __ vfcvt_f_x_v(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg)); + } + %} + ins_pipe(pipe_slow); +%} \ No newline at end of file diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index d2992b9012b..136508af21d 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * 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. @@ -978,6 +978,9 @@ static void gen_continuation_enter(MacroAssembler* masm, __ align(NativeInstruction::instruction_size); const address tr_call = __ trampoline_call(resolve); + if (tr_call == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } oop_maps->add_gc_map(__ pc() - start, map); __ post_call_nop(); @@ -985,7 +988,10 @@ static void gen_continuation_enter(MacroAssembler* masm, __ j(exit); CodeBuffer* cbuf = masm->code_section()->outer(); - CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + if (stub == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } } // compiled entry @@ -1005,6 +1011,9 @@ static void gen_continuation_enter(MacroAssembler* masm, __ align(NativeInstruction::instruction_size); const address tr_call = __ trampoline_call(resolve); + if (tr_call == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } oop_maps->add_gc_map(__ pc() - start, map); __ post_call_nop(); @@ -1045,7 +1054,10 @@ static void gen_continuation_enter(MacroAssembler* masm, } CodeBuffer* cbuf = masm->code_section()->outer(); - CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + if (stub == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } } static void gen_continuation_yield(MacroAssembler* masm, diff --git a/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp b/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp index 9fb17e6e4e2..38ee1de6470 100644 --- a/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 5bc26b9cbfe..4f34f824bd5 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -2461,7 +2461,7 @@ class StubGenerator: public StubCodeGenerator { if (bs_asm->nmethod_patching_type() == NMethodPatchingType::conc_instruction_and_data_patch) { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); - Address thread_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset()) + 4); + Address thread_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()) + 4); __ la(t1, ExternalAddress(bs_asm->patching_epoch_addr())); __ lwu(t1, t1); __ sw(t1, thread_epoch_addr); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 49a2b87c232..213e360c20e 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -776,8 +776,12 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // Move SP out of the way __ mv(sp, t0); } else { - __ sd(sp, Address(sp, 5 * wordSize)); + // Make sure there is room for the exception oop pushed in case method throws + // an exception (see TemplateInterpreterGenerator::generate_throw_exception()) + __ sub(t0, sp, 2 * wordSize); + __ sd(t0, Address(sp, 5 * wordSize)); __ sd(zr, Address(sp, 4 * wordSize)); + __ mv(sp, t0); } } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 6afef7ae546..9ba73a00808 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -59,6 +59,9 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseZbb)) { FLAG_SET_DEFAULT(UseZbb, true); } + if (FLAG_IS_DEFAULT(UseZbs)) { + FLAG_SET_DEFAULT(UseZbs, true); + } if (FLAG_IS_DEFAULT(UseZic64b)) { FLAG_SET_DEFAULT(UseZic64b, true); } @@ -71,6 +74,9 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseZicboz)) { FLAG_SET_DEFAULT(UseZicboz, true); } + if (FLAG_IS_DEFAULT(UseZfhmin)) { + FLAG_SET_DEFAULT(UseZfhmin, true); + } } if (UseZic64b) { diff --git a/src/hotspot/cpu/riscv/vmstorage_riscv.hpp b/src/hotspot/cpu/riscv/vmstorage_riscv.hpp new file mode 100644 index 00000000000..93940376229 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmstorage_riscv.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 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_RISCV_VMSTORAGE_RISCV_INLINE_HPP +#define CPU_RISCV_VMSTORAGE_RISCV_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_RISCV_VMSTORAGE_RISCV_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index 4258f971078..a0a86a707dd 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -295,7 +295,7 @@ class AddressLiteral { protected: // creation - AddressLiteral() : _address(NULL), _rspec(NULL) {} + AddressLiteral() : _address(NULL), _rspec() {} public: AddressLiteral(address addr, RelocationHolder const& rspec) diff --git a/src/hotspot/cpu/s390/c1_Defs_s390.hpp b/src/hotspot/cpu/s390/c1_Defs_s390.hpp index 8ee07273b3b..3fc3ee2772c 100644 --- a/src/hotspot/cpu/s390/c1_Defs_s390.hpp +++ b/src/hotspot/cpu/s390/c1_Defs_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -68,4 +68,8 @@ enum { pd_float_saved_as_double = false }; +enum { + pd_two_operand_lir_form = true +}; + #endif // CPU_S390_C1_DEFS_S390_HPP diff --git a/src/hotspot/cpu/s390/c1_globals_s390.hpp b/src/hotspot/cpu/s390/c1_globals_s390.hpp index a939b32bd5b..130a53ad084 100644 --- a/src/hotspot/cpu/s390/c1_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c1_globals_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -61,6 +61,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, false); define_pd_global(bool, CSEArrayLength, true); -define_pd_global(bool, TwoOperandLIRForm, true); #endif // CPU_S390_C1_GLOBALS_S390_HPP diff --git a/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp b/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp index a97e700ee3a..5b9c5d9a8bd 100644 --- a/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp +++ b/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp index af69f2a58a6..37b6f43ac14 100644 --- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp +++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp index 918e89f3ee6..5438cbe5cd6 100644 --- a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp +++ b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,24 +34,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp index ea7b6a4552c..97df78d12d8 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp @@ -135,7 +135,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { __ load_const(Z_R1_scratch, (uint64_t)StubRoutines::zarch::nmethod_entry_barrier()); // 2*6 bytes // Load value from current java object: - __ z_lg(Z_R0_scratch, in_bytes(bs_nm->thread_disarmed_offset()), Z_thread); // 6 bytes + __ z_lg(Z_R0_scratch, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), Z_thread); // 6 bytes // Compare to current patched value: __ z_cfi(Z_R0_scratch, /* to be patched */ -1); // 6 bytes (2 + 4 byte imm val) diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp index 46089266f8e..a912cfcaf82 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp @@ -101,29 +101,20 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { return; } -void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { if (!supports_entry_barrier(nm)) { return; } NativeMethodBarrier* barrier = get_nmethod_barrier(nm); - barrier->set_guard_value(arm_value); + barrier->set_guard_value(value); } -void BarrierSetNMethod::disarm(nmethod* nm) { +int BarrierSetNMethod::guard_value(nmethod* nm) { if (!supports_entry_barrier(nm)) { - return; - } - - NativeMethodBarrier* barrier = get_nmethod_barrier(nm); - barrier->set_guard_value(disarmed_value()); -} - -bool BarrierSetNMethod::is_armed(nmethod* nm) { - if (!supports_entry_barrier(nm)) { - return false; + return disarmed_guard_value(); } NativeMethodBarrier* barrier = get_nmethod_barrier(nm); - return barrier->get_guard_value() != disarmed_value(); + return barrier->get_guard_value(); } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 5a26adf5ec9..46897266b20 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -3858,7 +3858,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, @@ -3877,7 +3877,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index 436271c3022..d683f35a8a4 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -153,6 +153,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp b/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp index 2df1e38a9de..4f372c982d5 100644 --- a/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp +++ b/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/s390/vmstorage_s390.hpp b/src/hotspot/cpu/s390/vmstorage_s390.hpp new file mode 100644 index 00000000000..702e57efb94 --- /dev/null +++ b/src/hotspot/cpu/s390/vmstorage_s390.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 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_S390_VMSTORAGE_S390_INLINE_HPP +#define CPU_S390_VMSTORAGE_S390_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_S390_VMSTORAGE_S390_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index ad7543cfb78..67ff8a97c7a 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -1931,14 +1931,14 @@ void Assembler::vcvtdq2pd(XMMRegister dst, XMMRegister src, int vector_len) { } void Assembler::vcvtps2ph(XMMRegister dst, XMMRegister src, int imm8, int vector_len) { - assert(VM_Version::supports_avx512vl() || VM_Version::supports_f16c(), ""); + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /*uses_vl */ true); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int24(0x1D, (0xC0 | encode), imm8); } void Assembler::evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm8, int vector_len) { - assert(VM_Version::supports_avx512vl(), ""); + assert(VM_Version::supports_evex(), ""); InstructionMark im(this); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /*uses_vl */ true); attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_64bit); @@ -1951,13 +1951,34 @@ void Assembler::evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm emit_int8(imm8); } +void Assembler::vcvtps2ph(Address dst, XMMRegister src, int imm8, int vector_len) { + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /*uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x1D); + emit_operand(src, dst, 1); + emit_int8(imm8); +} + void Assembler::vcvtph2ps(XMMRegister dst, XMMRegister src, int vector_len) { - assert(VM_Version::supports_avx512vl() || VM_Version::supports_f16c(), ""); + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int16(0x13, (0xC0 | encode)); } +void Assembler::vcvtph2ps(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /*uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x13); + emit_operand(dst, src, 0); +} + void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2474,7 +2495,7 @@ void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { assert(dest != NULL, "must have a target"); intptr_t disp = dest - (pc() + sizeof(int32_t)); assert(is_simm32(disp), "must be 32bit offset (jmp)"); - emit_data(disp, rspec.reloc(), call32_operand); + emit_data(disp, rspec, call32_operand); } void Assembler::jmpb_0(Label& L, const char* file, int line) { @@ -5426,13 +5447,38 @@ void Assembler::vptest(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x17, (0xC0 | encode)); } +void Assembler::vtestps(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x0E, (0xC0 | encode)); +} + void Assembler::evptestmb(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { - assert(VM_Version::supports_avx512vlbw(), ""); - // Encoding: EVEX.NDS.XXX.66.0F.W0 DB /r + assert(vector_len == AVX_512bit ? VM_Version::supports_avx512bw() : VM_Version::supports_avx512vlbw(), ""); + // Encoding: EVEX.NDS.XXX.66.0F38.W0 DB /r + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x26, (0xC0 | encode)); +} + +void Assembler::evptestmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx512vl(), ""); + // Encoding: EVEX.NDS.XXX.66.0F38.W0 DB /r InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); - emit_int16((unsigned char)0x26, (0xC0 | encode)); + emit_int16(0x27, (0xC0 | encode)); +} + +void Assembler::evptestnmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx512vl(), ""); + // Encoding: EVEX.NDS.XXX.F3.0F38.W0 DB /r + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x27, (0xC0 | encode)); } void Assembler::punpcklbw(XMMRegister dst, Address src) { @@ -13407,6 +13453,11 @@ void Assembler::orq(Register dst, int32_t imm32) { emit_arith(0x81, 0xC8, dst, imm32); } +void Assembler::orq_imm32(Register dst, int32_t imm32) { + (void) prefixq_and_encode(dst->encoding()); + emit_arith_imm32(0x81, 0xC8, dst, imm32); +} + void Assembler::orq(Register dst, Address src) { InstructionMark im(this); emit_int16(get_prefixq(src, dst), 0x0B); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 7b4288e775e..a4bd8bf4864 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -1160,6 +1160,8 @@ class Assembler : public AbstractAssembler { void vcvtps2ph(XMMRegister dst, XMMRegister src, int imm8, int vector_len); void vcvtph2ps(XMMRegister dst, XMMRegister src, int vector_len); void evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm8, int vector_len); + void vcvtps2ph(Address dst, XMMRegister src, int imm8, int vector_len); + void vcvtph2ps(XMMRegister dst, Address src, int vector_len); // Convert Packed Signed Doubleword Integers to Packed Single-Precision Floating-Point Value void cvtdq2ps(XMMRegister dst, XMMRegister src); @@ -1734,6 +1736,7 @@ class Assembler : public AbstractAssembler { void orq(Address dst, int32_t imm32); void orq(Address dst, Register src); void orq(Register dst, int32_t imm32); + void orq_imm32(Register dst, int32_t imm32); void orq(Register dst, Address src); void orq(Register dst, Register src); @@ -1971,9 +1974,12 @@ class Assembler : public AbstractAssembler { void vptest(XMMRegister dst, Address src); void evptestmb(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evptestmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evptestnmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); // Vector compare void vptest(XMMRegister dst, XMMRegister src, int vector_len); + void vtestps(XMMRegister dst, XMMRegister src, int vector_len); // Interleave Low Bytes void punpcklbw(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/c1_Defs_x86.hpp b/src/hotspot/cpu/x86/c1_Defs_x86.hpp index c8529d9afda..40a48622571 100644 --- a/src/hotspot/cpu/x86/c1_Defs_x86.hpp +++ b/src/hotspot/cpu/x86/c1_Defs_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -75,4 +75,8 @@ enum { pd_float_saved_as_double = true }; +enum { + pd_two_operand_lir_form = true +}; + #endif // CPU_X86_C1_DEFS_X86_HPP diff --git a/src/hotspot/cpu/x86/c1_globals_x86.hpp b/src/hotspot/cpu/x86/c1_globals_x86.hpp index 9212e321d65..b2085a0b4b3 100644 --- a/src/hotspot/cpu/x86/c1_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c1_globals_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -59,6 +59,5 @@ define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, OptimizeSinglePrecision, true ); define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, true ); #endif // CPU_X86_C1_GLOBALS_X86_HPP diff --git a/src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp similarity index 72% rename from src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp rename to src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp index c3d4850a5db..acae574bcf3 100644 --- a/src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp +++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,22 +23,26 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 33; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(masm.pc() - masm.offset() + _safepoint_offset); #ifdef _LP64 __ lea(rscratch1, safepoint_pc); __ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1); @@ -57,4 +61,15 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP #endif __ jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + return 10; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + __ call(RuntimeAddress(StubRoutines::x86::method_entry_barrier())); + __ jmp(continuation(), false /* maybe_short */); +} + #undef __ diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 26c19ee6f1d..91949213a20 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -138,8 +138,9 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool Label* continuation = &dummy_continuation; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for the purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); } bs->nmethod_entry_barrier(this, slow_path, continuation); @@ -151,16 +152,6 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool } } -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - bind(stub->slow_path()); - call(RuntimeAddress(StubRoutines::x86::method_entry_barrier())); - jmp(stub->continuation(), false /* maybe_short */); -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 10; -} - inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vlen_in_bytes) { switch (vlen_in_bytes) { case 4: // fall-through @@ -2415,58 +2406,32 @@ void C2_MacroAssembler::evpblend(BasicType typ, XMMRegister dst, KRegister kmask } } -void C2_MacroAssembler::vectortest(int bt, int vlen, XMMRegister src1, XMMRegister src2, - XMMRegister vtmp1, XMMRegister vtmp2, KRegister mask) { - switch(vlen) { - case 4: - assert(vtmp1 != xnoreg, "required."); - // Broadcast lower 32 bits to 128 bits before ptest - pshufd(vtmp1, src1, 0x0); - if (bt == BoolTest::overflow) { - assert(vtmp2 != xnoreg, "required."); - pshufd(vtmp2, src2, 0x0); - } else { - assert(vtmp2 == xnoreg, "required."); - vtmp2 = src2; - } - ptest(vtmp1, vtmp2); - break; - case 8: - assert(vtmp1 != xnoreg, "required."); - // Broadcast lower 64 bits to 128 bits before ptest - pshufd(vtmp1, src1, 0x4); - if (bt == BoolTest::overflow) { - assert(vtmp2 != xnoreg, "required."); - pshufd(vtmp2, src2, 0x4); - } else { - assert(vtmp2 == xnoreg, "required."); - vtmp2 = src2; - } - ptest(vtmp1, vtmp2); - break; - case 16: - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - ptest(src1, src2); - break; - case 32: - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - vptest(src1, src2, Assembler::AVX_256bit); - break; - case 64: - { - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - evpcmpeqb(mask, src1, src2, Assembler::AVX_512bit); - if (bt == BoolTest::ne) { - ktestql(mask, mask); - } else { - assert(bt == BoolTest::overflow, "required"); - kortestql(mask, mask); - } - } - break; - default: - assert(false,"Should not reach here."); - break; +void C2_MacroAssembler::vectortest(BasicType bt, XMMRegister src1, XMMRegister src2, XMMRegister vtmp, int vlen_in_bytes) { + assert(vlen_in_bytes <= 32, ""); + int esize = type2aelembytes(bt); + if (vlen_in_bytes == 32) { + assert(vtmp == xnoreg, "required."); + if (esize >= 4) { + vtestps(src1, src2, AVX_256bit); + } else { + vptest(src1, src2, AVX_256bit); + } + return; + } + if (vlen_in_bytes < 16) { + // Duplicate the lower part to fill the whole register, + // Don't need to do so for src2 + assert(vtmp != xnoreg, "required"); + int shuffle_imm = (vlen_in_bytes == 4) ? 0x00 : 0x04; + pshufd(vtmp, src1, shuffle_imm); + } else { + assert(vtmp == xnoreg, "required"); + vtmp = src1; + } + if (esize >= 4 && VM_Version::supports_avx()) { + vtestps(vtmp, src2, AVX_128bit); + } else { + ptest(vtmp, src2); } } diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 029918a4f36..2bd90fc24ea 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -138,8 +138,7 @@ void get_elem(BasicType typ, XMMRegister dst, XMMRegister src, int elemindex, XMMRegister vtmp = xnoreg); // vector test - void vectortest(int bt, int vlen, XMMRegister src1, XMMRegister src2, - XMMRegister vtmp1 = xnoreg, XMMRegister vtmp2 = xnoreg, KRegister mask = knoreg); + void vectortest(BasicType bt, XMMRegister src1, XMMRegister src2, XMMRegister vtmp, int vlen_in_bytes); // Covert B2X void vconvert_b2x(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vlen_enc); diff --git a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp index 0b2b51f6e45..fc804b3795a 100644 --- a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp +++ b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp @@ -199,11 +199,6 @@ inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { assert(!PreserveFramePointer, "Frame pointers need to be fixed"); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - frame::sender_sp_offset) = fp; -} - // Slow path inline frame ThawBase::new_entry_frame() { diff --git a/src/hotspot/cpu/x86/crc32c.h b/src/hotspot/cpu/x86/crc32c.h index dfdbd525e77..b2d4a90619d 100644 --- a/src/hotspot/cpu/x86/crc32c.h +++ b/src/hotspot/cpu/x86/crc32c.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 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 @@ -39,15 +39,15 @@ enum { // based on ubench study using methodology described in // V. Gopal et al. / Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction April 2011 8 // - // arbitrary value between 27 and 256 - CRC32C_MIDDLE = 8 * 86, + // arbitrary value between 9 and 256 + CRC32C_MIDDLE = 8 * 74, // V. Gopal et al. / Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction April 2011 9 - // shows that 240 and 1024 are equally good choices as the 216==8*27 + // shows that 240 and 1024 are equally good choices as the 216==8*9*3 // // Selecting the smallest value which resulted in a significant performance improvement over // sequential version - CRC32C_LOW = 8 * 27, + CRC32C_LOW = 8 * 9, CRC32C_NUM_ChunkSizeInBytes = 3, diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp index 3fc43c5031e..3f1241970f2 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp @@ -28,9 +28,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index 06bf0099a91..9637057b6ab 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -41,13 +41,14 @@ class DowncallStubGenerator : public StubCodeGenerator { BasicType _ret_bt; const ABIDescriptor& _abi; - const GrowableArray& _input_registers; - const GrowableArray& _output_registers; + const GrowableArray& _input_registers; + const GrowableArray& _output_registers; bool _needs_return_buffer; + int _captured_state_mask; int _frame_complete; - int _framesize; + int _frame_size_slots; OopMapSet* _oop_maps; public: DowncallStubGenerator(CodeBuffer* buffer, @@ -55,9 +56,10 @@ class DowncallStubGenerator : public StubCodeGenerator { int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) : StubCodeGenerator(buffer, PrintMethodHandleStubs), _signature(signature), _num_args(num_args), @@ -66,8 +68,9 @@ class DowncallStubGenerator : public StubCodeGenerator { _input_registers(input_registers), _output_registers(output_registers), _needs_return_buffer(needs_return_buffer), + _captured_state_mask(captured_state_mask), _frame_complete(0), - _framesize(0), + _frame_size_slots(0), _oop_maps(NULL) { } @@ -77,8 +80,8 @@ class DowncallStubGenerator : public StubCodeGenerator { return _frame_complete; } - int framesize() const { - return (_framesize >> (LogBytesPerWord - LogBytesPerInt)); + int framesize() const { // frame size in 64-bit words + return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt)); } OopMapSet* oop_maps() const { @@ -92,12 +95,15 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { - int locs_size = 64; + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { + int locs_size = 64; CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size); - DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer); + DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, + input_registers, output_registers, + needs_return_buffer, captured_state_mask); g.generate(); code.log_section_sizes("nep_invoker_blob"); @@ -133,10 +139,10 @@ void DowncallStubGenerator::generate() { // out arg area (e.g. for stack args) }; - Register shufffle_reg = rbx; + VMStorage shuffle_reg = as_VMStorage(rbx); JavaCallingConvention in_conv; NativeCallingConvention out_conv(_input_registers); - ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shufffle_reg->as_VMReg()); + ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg); #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; @@ -149,34 +155,38 @@ void DowncallStubGenerator::generate() { // in bytes int allocated_frame_size = 0; - if (_needs_return_buffer) { - allocated_frame_size += 8; // store address - } - allocated_frame_size += arg_shuffle.out_arg_stack_slots() << LogBytesPerInt; allocated_frame_size += _abi._shadow_space_bytes; + allocated_frame_size += arg_shuffle.out_arg_bytes(); - int ret_buf_addr_rsp_offset = -1; - if (_needs_return_buffer) { - // the above - ret_buf_addr_rsp_offset = allocated_frame_size - 8; - } - - // when we don't use a return buffer we need to spill the return value around our slowpath calls - // when we use a return buffer case this SHOULD be unused. + // when we don't use a return buffer we need to spill the return value around our slow path calls + bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); int spill_rsp_offset = -1; - if (!_needs_return_buffer) { + if (should_save_return_value) { spill_rsp_offset = 0; - // spill area can be shared with the above, so we take the max of the 2 + // spill area can be shared with shadow space and out args, + // since they are only used before the call, + // and spill area is only used after. allocated_frame_size = out_reg_spiller.spill_size_bytes() > allocated_frame_size ? out_reg_spiller.spill_size_bytes() : allocated_frame_size; } + + StubLocations locs; + locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch1); + if (_needs_return_buffer) { + locs.set_frame_data(StubLocations::RETURN_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + if (_captured_state_mask != 0) { + locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + allocated_frame_size = align_up(allocated_frame_size, 16); - // _framesize is in 32-bit stack slots: - _framesize += framesize_base + (allocated_frame_size >> LogBytesPerInt); - assert(is_even(_framesize/2), "sp not 16-byte aligned"); + _frame_size_slots += framesize_base + (allocated_frame_size >> LogBytesPerInt); + assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned"); _oop_maps = new OopMapSet(); address start = __ pc(); @@ -192,7 +202,7 @@ void DowncallStubGenerator::generate() { __ block_comment("{ thread java2native"); __ set_last_Java_frame(rsp, rbp, (address)the_pc, rscratch1); - OopMap* map = new OopMap(_framesize, 0); + OopMap* map = new OopMap(_frame_size_slots, 0); _oop_maps->add_gc_map(the_pc - start, map); // State transition @@ -200,45 +210,22 @@ void DowncallStubGenerator::generate() { __ block_comment("} thread java2native"); __ block_comment("{ argument shuffle"); - arg_shuffle.generate(_masm, shufffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes); - if (_needs_return_buffer) { - // spill our return buffer address - assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill"); - __ movptr(Address(rsp, ret_buf_addr_rsp_offset), _abi._ret_buf_addr_reg); - } + arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs); __ block_comment("} argument shuffle"); - __ call(_abi._target_addr_reg); + __ call(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed r15_thread - if (!_needs_return_buffer) { - // FIXME: this assumes we return in rax/xmm0, which might not be the case - // Unpack native results. - switch (_ret_bt) { - case T_BOOLEAN: __ c2bool(rax); break; - case T_CHAR : __ movzwl(rax, rax); break; - case T_BYTE : __ sign_extend_byte (rax); break; - case T_SHORT : __ sign_extend_short(rax); break; - case T_INT : /* nothing to do */ break; - case T_DOUBLE : - case T_FLOAT : - // Result is in xmm0 we'll save as needed - break; - case T_VOID: break; - case T_LONG: break; - default : ShouldNotReachHere(); - } - } else { - assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill"); - __ movptr(rscratch1, Address(rsp, ret_buf_addr_rsp_offset)); + if (_needs_return_buffer) { + __ movptr(rscratch1, Address(rsp, locs.data_offset(StubLocations::RETURN_BUFFER))); int offset = 0; for (int i = 0; i < _output_registers.length(); i++) { - VMReg reg = _output_registers.at(i); - if (reg->is_Register()) { - __ movptr(Address(rscratch1, offset), reg->as_Register()); + VMStorage reg = _output_registers.at(i); + if (reg.type() == StorageType::INTEGER) { + __ movptr(Address(rscratch1, offset), as_Register(reg)); offset += 8; - } else if (reg->is_XMMRegister()) { - __ movdqu(Address(rscratch1, offset), reg->as_XMMRegister()); + } else if (reg.type() == StorageType::VECTOR) { + __ movdqu(Address(rscratch1, offset), as_XMMRegister(reg)); offset += 16; } else { ShouldNotReachHere(); @@ -246,6 +233,34 @@ void DowncallStubGenerator::generate() { } } + ////////////////////////////////////////////////////////////////////////////// + + if (_captured_state_mask != 0) { + __ block_comment("{ save thread local"); + __ vzeroupper(); + + if (should_save_return_value) { + out_reg_spiller.generate_spill(_masm, spill_rsp_offset); + } + + __ movptr(c_rarg0, Address(rsp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movl(c_rarg1, _captured_state_mask); + __ 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, DowncallLinker::capture_state))); + __ mov(rsp, r12); // restore sp + __ reinit_heapbase(); + + if (should_save_return_value) { + out_reg_spiller.generate_fill(_masm, spill_rsp_offset); + } + + __ block_comment("} save thread local"); + } + + ////////////////////////////////////////////////////////////////////////////// + __ block_comment("{ thread native2java"); __ restore_cpu_control_state_after_jni(rscratch1); @@ -289,7 +304,7 @@ void DowncallStubGenerator::generate() { __ bind(L_safepoint_poll_slow_path); __ vzeroupper(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_rsp_offset); } @@ -301,7 +316,7 @@ void DowncallStubGenerator::generate() { __ mov(rsp, r12); // restore sp __ reinit_heapbase(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_rsp_offset); } @@ -314,7 +329,7 @@ void DowncallStubGenerator::generate() { __ bind(L_reguard); __ vzeroupper(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_rsp_offset); } @@ -325,7 +340,7 @@ void DowncallStubGenerator::generate() { __ mov(rsp, r12); // restore sp __ reinit_heapbase(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_rsp_offset); } diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86.hpp b/src/hotspot/cpu/x86/foreignGlobals_x86.hpp index 160aa468539..19999a416ea 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86.hpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86.hpp @@ -40,8 +40,8 @@ struct ABIDescriptor { int32_t _stack_alignment_bytes; int32_t _shadow_space_bytes; - Register _target_addr_reg; - Register _ret_buf_addr_reg; + VMStorage _scratch1; + VMStorage _scratch2; bool is_volatile_reg(Register reg) const; bool is_volatile_reg(XMMRegister reg) const; diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp b/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp index e196727674d..8a31955f4d1 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp @@ -33,24 +33,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp b/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp index 3b3d5ff00df..74afbe4fd61 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp @@ -40,123 +40,154 @@ bool ABIDescriptor::is_volatile_reg(XMMRegister reg) const { || _vector_additional_volatile_registers.contains(reg); } -static constexpr int INTEGER_TYPE = 0; -static constexpr int VECTOR_TYPE = 1; -static constexpr int X87_TYPE = 2; - const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { oop abi_oop = JNIHandles::resolve_non_null(jabi); ABIDescriptor abi; objArrayOop inputStorage = jdk_internal_foreign_abi_ABIDescriptor::inputStorage(abi_oop); - parse_register_array(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, as_Register); - parse_register_array(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_XMMRegister); + parse_register_array(inputStorage, StorageType::INTEGER, abi._integer_argument_registers, as_Register); + parse_register_array(inputStorage, StorageType::VECTOR, abi._vector_argument_registers, as_XMMRegister); objArrayOop outputStorage = jdk_internal_foreign_abi_ABIDescriptor::outputStorage(abi_oop); - parse_register_array(outputStorage, INTEGER_TYPE, abi._integer_return_registers, as_Register); - parse_register_array(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_XMMRegister); - objArrayOop subarray = oop_cast(outputStorage->obj_at(X87_TYPE)); + parse_register_array(outputStorage, StorageType::INTEGER, abi._integer_return_registers, as_Register); + parse_register_array(outputStorage, StorageType::VECTOR, abi._vector_return_registers, as_XMMRegister); + objArrayOop subarray = oop_cast(outputStorage->obj_at((int) StorageType::X87)); abi._X87_return_registers_noof = subarray->length(); objArrayOop volatileStorage = jdk_internal_foreign_abi_ABIDescriptor::volatileStorage(abi_oop); - parse_register_array(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, as_Register); - parse_register_array(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_XMMRegister); + parse_register_array(volatileStorage, StorageType::INTEGER, abi._integer_additional_volatile_registers, as_Register); + parse_register_array(volatileStorage, StorageType::VECTOR, abi._vector_additional_volatile_registers, as_XMMRegister); abi._stack_alignment_bytes = jdk_internal_foreign_abi_ABIDescriptor::stackAlignment(abi_oop); abi._shadow_space_bytes = jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(abi_oop); - abi._target_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(abi_oop))->as_Register(); - abi._ret_buf_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(abi_oop))->as_Register(); + abi._scratch1 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch1(abi_oop)); + abi._scratch2 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch2(abi_oop)); return abi; } -enum class RegType { - INTEGER = 0, - VECTOR = 1, - X87 = 2, - STACK = 3 -}; - -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - switch(static_cast(type)) { - case RegType::INTEGER: return ::as_Register(index)->as_VMReg(); - case RegType::VECTOR: return ::as_XMMRegister(index)->as_VMReg(); - case RegType::STACK: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); // numbering on x64 goes per 64-bits - case RegType::X87: break; - } - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { - if (reg->is_Register()) { +int RegSpiller::pd_reg_size(VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { return 8; - } else if (reg->is_XMMRegister()) { + } else if (reg.type() == StorageType::VECTOR) { return 16; } return 0; // stack and BAD } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->movptr(Address(rsp, offset), reg->as_Register()); - } else if (reg->is_XMMRegister()) { - masm->movdqu(Address(rsp, offset), reg->as_XMMRegister()); +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->movptr(Address(rsp, offset), as_Register(reg)); + } else if (reg.type() == StorageType::VECTOR) { + masm->movdqu(Address(rsp, offset), as_XMMRegister(reg)); } else { // stack and BAD } } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->movptr(reg->as_Register(), Address(rsp, offset)); - } else if (reg->is_XMMRegister()) { - masm->movdqu(reg->as_XMMRegister(), Address(rsp, offset)); +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->movptr(as_Register(reg), Address(rsp, offset)); + } else if (reg.type() == StorageType::VECTOR) { + masm->movdqu(as_XMMRegister(reg), Address(rsp, offset)); } else { // stack and BAD } } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { - Register tmp_reg = tmp->as_Register(); +static constexpr int RBP_BIAS = 16; // skip old rbp and return address + +static void move_reg64(MacroAssembler* masm, int out_stk_bias, + Register from_reg, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_reg); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(Address(rsp, to_reg.offset() + out_bias), from_reg); + break; + default: ShouldNotReachHere(); + } +} + +static void move_stack64(MacroAssembler* masm, Register tmp_reg, int out_stk_bias, + Address from_address, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_address); + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == XMM_MASK, "only moves to xmm registers supported"); + masm->movdqu(as_XMMRegister(to_reg), from_address); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(tmp_reg, from_address); + masm->movq(Address(rsp, to_reg.offset() + out_bias), tmp_reg); + break; + default: ShouldNotReachHere(); + } +} + +static void move_xmm(MacroAssembler* masm, int out_stk_bias, + XMMRegister from_reg, VMStorage to_reg) { + switch (to_reg.type()) { + case StorageType::INTEGER: // windows vargarg floats + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_reg); + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == XMM_MASK, "only moves to xmm registers supported"); + masm->movdqu(as_XMMRegister(to_reg), from_reg); + break; + case StorageType::STACK: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(Address(rsp, to_reg.offset() + out_stk_bias), from_reg); + break; + default: ShouldNotReachHere(); + } +} + +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { + Register tmp_reg = as_Register(tmp); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; - VMRegPair from_vmreg = move.from; - VMRegPair to_vmreg = move.to; - - masm->block_comment(err_msg("bt=%s", null_safe_string(type2name(arg_bt)))); - switch (arg_bt) { - case T_BOOLEAN: - case T_BYTE: - case T_SHORT: - case T_CHAR: - case T_INT: - masm->move32_64(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - break; + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; - case T_FLOAT: - if (to_vmreg.first()->is_Register()) { // Windows vararg call - masm->movq(to_vmreg.first()->as_Register(), from_vmreg.first()->as_XMMRegister()); - } else { - masm->float_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - } - break; + // replace any placeholders + if (from_reg.type() == StorageType::PLACEHOLDER) { + from_reg = locs.get(from_reg); + } + if (to_reg.type() == StorageType::PLACEHOLDER) { + to_reg = locs.get(to_reg); + } - case T_DOUBLE: - if (to_vmreg.first()->is_Register()) { // Windows vararg call - masm->movq(to_vmreg.first()->as_Register(), from_vmreg.first()->as_XMMRegister()); - } else { - masm->double_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - } + switch (from_reg.type()) { + case StorageType::INTEGER: + assert(from_reg.segment_mask() == REG64_MASK, "only 64-bit register supported"); + move_reg64(masm, out_stk_bias, as_Register(from_reg), to_reg); break; - - case T_LONG: - masm->long_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); + case StorageType::VECTOR: + assert(from_reg.segment_mask() == XMM_MASK, "only xmm register supported"); + move_xmm(masm, out_stk_bias, as_XMMRegister(from_reg), to_reg); break; - - default: - fatal("found in upcall args: %s", type2name(arg_bt)); + case StorageType::STACK: { + assert(from_reg.stack_size() == 8, "only stack_size 8 supported"); + Address from_addr(rbp, RBP_BIAS + from_reg.offset() + in_stk_bias); + move_stack64(masm, tmp_reg, out_stk_bias, from_addr, to_reg); + } break; + default: ShouldNotReachHere(); } } } diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index 51a22b50163..58df83d4e4d 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -279,7 +279,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo return; } Register thread = r15_thread; - Address disarmed_addr(thread, in_bytes(bs_nm->thread_disarmed_offset())); + Address disarmed_addr(thread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); // The immediate is the last 4 bytes, so if we align the start of the cmp // instruction to 4 bytes, we know that the second half of it is also 4 // byte aligned, which means that the immediate will not cross a cache line @@ -310,7 +310,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label*, La Register tmp = rdi; __ push(tmp); - __ movptr(tmp, (intptr_t)bs_nm->disarmed_value_address()); + __ movptr(tmp, (intptr_t)bs_nm->disarmed_guard_value_address()); Address disarmed_addr(tmp, 0); __ align(4); __ cmpl_imm32(disarmed_addr, 0); diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp index fa2f18c5389..648d5fbabe9 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp @@ -56,7 +56,7 @@ class NativeNMethodCmpBarrier: public NativeInstruction { address instruction_address() const { return addr_at(0); } address immediate_address() const { return addr_at(imm_offset); } - jint get_immedate() const { return int_at(imm_offset); } + jint get_immediate() const { return int_at(imm_offset); } void set_immediate(jint imm) { set_int_at(imm_offset, imm); } void verify() const; }; @@ -176,29 +176,20 @@ static NativeNMethodCmpBarrier* native_nmethod_barrier(nmethod* nm) { return barrier; } -void BarrierSetNMethod::disarm(nmethod* nm) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { if (!supports_entry_barrier(nm)) { return; } NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm); - cmp->set_immediate(disarmed_value()); + cmp->set_immediate(value); } -void BarrierSetNMethod::arm(nmethod* nm, int arm_value) { +int BarrierSetNMethod::guard_value(nmethod* nm) { if (!supports_entry_barrier(nm)) { - return; - } - - NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm); - cmp->set_immediate(arm_value); -} - -bool BarrierSetNMethod::is_armed(nmethod* nm) { - if (!supports_entry_barrier(nm)) { - return false; + return disarmed_guard_value(); } NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm); - return (disarmed_value() != cmp->get_immedate()); + return cmp->get_immediate(); } 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 f3e19b41733..44f3f221fae 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -35,7 +35,7 @@ source %{ static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, uint8_t barrier_data) { if (barrier_data == ZLoadBarrierElided) { - return; // Elided. + return; } ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); { @@ -60,6 +60,27 @@ static void z_load_barrier_cmpxchg(MacroAssembler& _masm, const MachNode* node, __ bind(*stub->continuation()); } +static void z_cmpxchg_common(MacroAssembler& _masm, const MachNode* node, Register mem_reg, Register newval, Register tmp) { + // Compare value (oldval) is in rax + const Address mem = Address(mem_reg, 0); + + if (node->barrier_data() != ZLoadBarrierElided) { + __ movptr(tmp, rax); + } + + __ lock(); + __ cmpxchgptr(newval, mem); + + if (node->barrier_data() != ZLoadBarrierElided) { + Label good; + z_load_barrier_cmpxchg(_masm, node, mem, rax, tmp, good); + __ movptr(rax, tmp); + __ lock(); + __ cmpxchgptr(newval, mem); + __ bind(good); + } +} + %} // Load Pointer @@ -81,7 +102,7 @@ instruct zLoadP(rRegP dst, memory mem, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ +instruct zCompareAndExchangeP(indirect mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ match(Set oldval (CompareAndExchangeP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); effect(KILL cr, TEMP tmp); @@ -90,26 +111,14 @@ instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP t "cmpxchgq $newval, $mem" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - - if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - } + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); %} ins_pipe(pipe_cmpxchg); %} -instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ +instruct zCompareAndSwapP(rRegI res, indirect mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ match(Set res (CompareAndSwapP mem (Binary oldval newval))); match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); @@ -121,20 +130,10 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags "movzbl $res, $res" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - __ cmpptr($tmp$$Register, $oldval$$Register); + __ cmpptr($tmp$$Register, rax); } __ setb(Assembler::equal, $res$$Register); __ movzbl($res$$Register, $res$$Register); @@ -143,7 +142,7 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags ins_pipe(pipe_cmpxchg); %} -instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ +instruct zXChgP(indirect mem, rRegP newval, rFlagsReg cr) %{ match(Set newval (GetAndSetP mem newval)); predicate(UseZGC && n->as_LoadStore()->barrier_data() != 0); effect(KILL cr); @@ -151,7 +150,7 @@ instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ format %{ "xchgq $newval, $mem" %} ins_encode %{ - __ xchgptr($newval$$Register, $mem$$Address); + __ xchgptr($newval$$Register, Address($mem$$Register, 0)); z_load_barrier(_masm, this, Address(noreg, 0), $newval$$Register, noreg /* tmp */, barrier_data()); %} diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 387a63c804a..0a5314d8faa 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -5108,7 +5108,7 @@ void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -5120,7 +5120,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Reg void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); @@ -8228,24 +8228,27 @@ void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Registe addl(tmp1, in2); addq(tmp1, in1); - BIND(L_wordByWord); cmpq(in1, tmp1); - jcc(Assembler::greaterEqual, L_byteByByteProlog); - crc32(in_out, Address(in1, 0), 4); - addq(in1, 4); - jmp(L_wordByWord); + jccb(Assembler::greaterEqual, L_byteByByteProlog); + align(16); + BIND(L_wordByWord); + crc32(in_out, Address(in1, 0), 8); + addq(in1, 8); + cmpq(in1, tmp1); + jcc(Assembler::less, L_wordByWord); BIND(L_byteByByteProlog); andl(in2, 0x00000007); movl(tmp2, 1); - BIND(L_byteByByte); cmpl(tmp2, in2); jccb(Assembler::greater, L_exit); + BIND(L_byteByByte); crc32(in_out, Address(in1, 0), 1); incq(in1); incl(tmp2); - jmp(L_byteByByte); + cmpl(tmp2, in2); + jcc(Assembler::lessEqual, L_byteByByte); BIND(L_exit); } @@ -9013,26 +9016,6 @@ void MacroAssembler::evand(BasicType type, XMMRegister dst, KRegister mask, XMMR } } -void MacroAssembler::anytrue(Register dst, uint masklen, KRegister src1, KRegister src2) { - masklen = masklen < 8 ? 8 : masklen; - ktest(masklen, src1, src2); - setb(Assembler::notZero, dst); - movzbl(dst, dst); -} - -void MacroAssembler::alltrue(Register dst, uint masklen, KRegister src1, KRegister src2, KRegister kscratch) { - if (masklen < 8) { - knotbl(kscratch, src2); - kortestbl(src1, kscratch); - setb(Assembler::carrySet, dst); - movzbl(dst, dst); - } else { - ktest(masklen, src1, src2); - setb(Assembler::carrySet, dst); - movzbl(dst, dst); - } -} - void MacroAssembler::kortest(uint masklen, KRegister src1, KRegister src2) { switch(masklen) { case 8: diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5a0a3d8c9a1..2baff498df6 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1768,9 +1768,6 @@ class MacroAssembler: public Assembler { using Assembler::vpternlogq; void vpternlogq(XMMRegister dst, int imm8, XMMRegister src2, AddressLiteral src3, int vector_len, Register rscratch = noreg); - void alltrue(Register dst, uint masklen, KRegister src1, KRegister src2, KRegister kscratch); - void anytrue(Register dst, uint masklen, KRegister src, KRegister kscratch); - void cmov32( Condition cc, Register dst, Address src); void cmov32( Condition cc, Register dst, Register src); diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index bc6524aed55..82a39fe8b1d 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -183,6 +183,25 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Without predicated input, an all-one vector is needed for the alltrue vector test + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return is_alltrue && !is_predicate; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + if (!is_alltrue) { + return BoolTest::ne; + } + if (!is_predicate) { + return BoolTest::lt; + } + if ((vlen == 8 && !VM_Version::supports_avx512dq()) || vlen < 8) { + return BoolTest::eq; + } + return BoolTest::lt; + } + // Returns pre-selection estimated size of a vector operation. // Currently, it's a rudimentary heuristic based on emitted code size for complex // IR nodes used by unroll policy. Idea is to constrain unrolling factor and prevent diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index 83d12a809e0..e310646ba93 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_x86.hpp @@ -56,9 +56,9 @@ class Register { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } bool has_byte_register() const { return 0 <= raw_encoding() && raw_encoding() < number_of_byte_registers; } // derived registers, offsets, and addresses @@ -74,7 +74,7 @@ class Register { int operator==(const Register r) const { return _encoding == r._encoding; } int operator!=(const Register r) const { return _encoding != r._encoding; } - const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } + constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } }; extern Register::RegisterImpl all_RegisterImpls[Register::number_of_registers + 1] INTERNAL_VISIBILITY; @@ -202,9 +202,9 @@ class XMMRegister { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline XMMRegister successor() const; @@ -219,7 +219,7 @@ class XMMRegister { int operator==(const XMMRegister r) const { return _encoding == r._encoding; } int operator!=(const XMMRegister r) const { return _encoding != r._encoding; } - const XMMRegisterImpl* operator->() const { return XMMRegisterImpl::first() + _encoding; } + constexpr const XMMRegisterImpl* operator->() const { return XMMRegisterImpl::first() + _encoding; } // Actually available XMM registers for use, depending on actual CPU capabilities and flags. static int available_xmm_registers() { diff --git a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp index 70f10dc646d..6240de27b6b 100644 --- a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp +++ b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 95dc03200eb..d7a613052a3 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -3709,7 +3709,7 @@ void StubGenerator::generate_initial() { StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32(); } - if (UsePolyIntrinsics) { + if (UsePoly1305Intrinsics) { StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks(); } diff --git a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp index e37491edfe8..3e3214b51b1 100644 --- a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp @@ -175,12 +175,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, const CallRegs call_regs = ForeignGlobals::parse_call_regs(jconv); CodeBuffer buffer("upcall_stub", /* code_size = */ 2048, /* locs_size = */ 1024); - Register shuffle_reg = rbx; + VMStorage shuffle_reg = as_VMStorage(rbx); JavaCallingConvention out_conv; NativeCallingConvention in_conv(call_regs._arg_regs); - ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); - int stack_slots = SharedRuntime::out_preserve_stack_slots() + arg_shuffle.out_arg_stack_slots(); - int out_arg_area = align_up(stack_slots * VMRegImpl::stack_slot_size, StackAlignmentInBytes); + ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg); + int preserved_bytes = SharedRuntime::out_preserve_stack_slots() * VMRegImpl::stack_slot_size; + int stack_bytes = preserved_bytes + arg_shuffle.out_arg_bytes(); + int out_arg_area = align_up(stack_bytes , StackAlignmentInBytes); #ifndef PRODUCT LogTarget(Trace, foreign, upcall) lt; @@ -208,10 +209,14 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, int frame_data_offset = reg_save_area_offset + reg_save_area_size; int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData); + StubLocations locs; int ret_buf_offset = -1; if (needs_return_buffer) { ret_buf_offset = frame_bottom_offset; frame_bottom_offset += ret_buf_size; + // use a free register for shuffling code to pick up return + // buffer address from + locs.set(StubLocations::RETURN_BUFFER, abi._scratch1); } int frame_size = frame_bottom_offset; @@ -273,9 +278,9 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, arg_spilller.generate_fill(_masm, arg_save_area_offset); if (needs_return_buffer) { assert(ret_buf_offset != -1, "no return buffer allocated"); - __ lea(abi._ret_buf_addr_reg, Address(rsp, ret_buf_offset)); + __ lea(as_Register(locs.get(StubLocations::RETURN_BUFFER)), Address(rsp, ret_buf_offset)); } - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), abi._shadow_space_bytes, 0); + arg_shuffle.generate(_masm, shuffle_reg, abi._shadow_space_bytes, 0, locs); __ block_comment("} argument shuffle"); __ block_comment("{ receiver "); @@ -293,7 +298,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, if (!needs_return_buffer) { #ifdef ASSERT if (call_regs._ret_regs.length() == 1) { // 0 or 1 - VMReg j_expected_result_reg; + VMStorage j_expected_result_reg; switch (ret_type) { case T_BOOLEAN: case T_BYTE: @@ -301,19 +306,18 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, case T_CHAR: case T_INT: case T_LONG: - j_expected_result_reg = rax->as_VMReg(); + j_expected_result_reg = as_VMStorage(rax); break; case T_FLOAT: case T_DOUBLE: - j_expected_result_reg = xmm0->as_VMReg(); + j_expected_result_reg = as_VMStorage(xmm0); break; default: fatal("unexpected return type: %s", type2name(ret_type)); } // No need to move for now, since CallArranger can pick a return type // that goes in the same reg for both CCs. But, at least assert they are the same - assert(call_regs._ret_regs.at(0) == j_expected_result_reg, - "unexpected result register: %s != %s", call_regs._ret_regs.at(0)->name(), j_expected_result_reg->name()); + assert(call_regs._ret_regs.at(0) == j_expected_result_reg, "unexpected result register"); } #endif } else { @@ -321,12 +325,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, __ lea(rscratch1, Address(rsp, ret_buf_offset)); int offset = 0; for (int i = 0; i < call_regs._ret_regs.length(); i++) { - VMReg reg = call_regs._ret_regs.at(i); - if (reg->is_Register()) { - __ movptr(reg->as_Register(), Address(rscratch1, offset)); + VMStorage reg = call_regs._ret_regs.at(i); + if (reg.type() == StorageType::INTEGER) { + __ movptr(as_Register(reg), Address(rscratch1, offset)); offset += 8; - } else if (reg->is_XMMRegister()) { - __ movdqu(reg->as_XMMRegister(), Address(rscratch1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ movdqu(as_XMMRegister(reg), Address(rscratch1, offset)); offset += 16; } else { ShouldNotReachHere(); @@ -389,9 +393,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, receiver, in_ByteSize(frame_data_offset)); - if (TraceOptimizedUpcallStubs) { - blob->print_on(tty); +#ifndef PRODUCT + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + blob->print_on(&ls); } +#endif return blob->code_begin(); } diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 5a0a085401b..ba2da1fcd1a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -956,6 +956,7 @@ void VM_Version::get_processor_features() { if (UseAVX < 1) { _features &= ~CPU_AVX; _features &= ~CPU_VZEROUPPER; + _features &= ~CPU_F16C; } if (logical_processors_per_package() == 1) { @@ -1350,14 +1351,14 @@ void VM_Version::get_processor_features() { #ifdef _LP64 if (supports_avx512ifma() && supports_avx512vlbw() && MaxVectorSize >= 64) { - if (FLAG_IS_DEFAULT(UsePolyIntrinsics)) { - FLAG_SET_DEFAULT(UsePolyIntrinsics, true); + if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) { + FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); } } else #endif - if (UsePolyIntrinsics) { + if (UsePoly1305Intrinsics) { warning("Intrinsics for Poly1305 crypto hash functions not available on this CPU."); - FLAG_SET_DEFAULT(UsePolyIntrinsics, false); + FLAG_SET_DEFAULT(UsePoly1305Intrinsics, false); } #ifdef _LP64 diff --git a/src/hotspot/cpu/x86/vmstorage_x86.hpp b/src/hotspot/cpu/x86/vmstorage_x86.hpp new file mode 100644 index 00000000000..a6ad21b2179 --- /dev/null +++ b/src/hotspot/cpu/x86/vmstorage_x86.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 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_X86_VMSTORAGE_X86_INLINE_HPP +#define CPU_X86_VMSTORAGE_X86_INLINE_HPP + +#include + +#include "asm/register.hpp" +#include "code/vmreg.inline.hpp" + +// keep in sync with jdk/internal/foreign/abi/x64/X86_64Architecture +enum class StorageType : int8_t { + INTEGER = 0, + VECTOR = 1, + X87 = 2, + STACK = 3, + PLACEHOLDER = 4, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return type == StorageType::INTEGER || type == StorageType::VECTOR || type == StorageType::X87; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +constexpr uint16_t REG64_MASK = 0b0000000000001111; +constexpr uint16_t XMM_MASK = 0b0000000000000001; + +inline Register as_Register(VMStorage vms) { + assert(vms.type() == StorageType::INTEGER, "not the right type"); + return ::as_Register(vms.index()); +} + +inline XMMRegister as_XMMRegister(VMStorage vms) { + assert(vms.type() == StorageType::VECTOR, "not the right type"); + return ::as_XMMRegister(vms.index()); +} + +inline VMReg as_VMReg(VMStorage vms) { + switch (vms.type()) { + case StorageType::INTEGER: return as_Register(vms)->as_VMReg(); + case StorageType::VECTOR: return as_XMMRegister(vms)->as_VMReg(); + case StorageType::STACK: { + assert((vms.index() % VMRegImpl::stack_slot_size) == 0, "can not represent as VMReg"); + return VMRegImpl::stack2reg(vms.index() / VMRegImpl::stack_slot_size); + } + default: ShouldNotReachHere(); return VMRegImpl::Bad(); + } +} + +constexpr inline VMStorage as_VMStorage(Register reg) { + return VMStorage::reg_storage(StorageType::INTEGER, REG64_MASK, reg->encoding()); +} + +constexpr inline VMStorage as_VMStorage(XMMRegister reg) { + return VMStorage::reg_storage(StorageType::VECTOR, XMM_MASK, reg->encoding()); +} + +inline VMStorage as_VMStorage(VMReg reg) { + if (reg->is_Register()) { + return as_VMStorage(reg->as_Register()); + } else if (reg->is_XMMRegister()) { + return as_VMStorage(reg->as_XMMRegister()); + } else if (reg->is_stack()) { + return VMStorage::stack_storage(reg); + } else if (!reg->is_valid()) { + return VMStorage::invalid(); + } + + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_X86_VMSTORAGE_X86_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index a6f2adabb28..80f0c0f4b49 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1687,6 +1687,12 @@ const bool Matcher::match_rule_supported(int opcode) { return false; } break; + case Op_VectorCastF2HF: + case Op_VectorCastHF2F: + if (!VM_Version::supports_f16c() && !VM_Version::supports_evex()) { + return false; + } + break; } return true; // Match rules are supported by default. } @@ -1844,8 +1850,6 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; // Implementation limitation } else if (size_in_bits < 32) { return false; // Implementation limitation - } else if (size_in_bits == 512 && (VM_Version::supports_avx512bw() == false)) { - return false; // Implementation limitation } break; case Op_VectorLoadShuffle: @@ -1901,6 +1905,14 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; + case Op_VectorCastF2HF: + case Op_VectorCastHF2F: + if (!VM_Version::supports_f16c() && + ((!VM_Version::supports_evex() || + ((size_in_bits != 512) && !VM_Version::supports_avx512vl())))) { + return false; + } + break; case Op_RoundVD: if (!VM_Version::supports_avx512dq()) { return false; @@ -3673,6 +3685,26 @@ instruct convF2HF_mem_reg(memory mem, regF src, kReg ktmp, rRegI rtmp) %{ ins_pipe( pipe_slow ); %} +instruct vconvF2HF(vec dst, vec src) %{ + match(Set dst (VectorCastF2HF src)); + format %{ "vector_conv_F2HF $dst $src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this, $src); + __ vcvtps2ph($dst$$XMMRegister, $src$$XMMRegister, 0x04, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vconvF2HF_mem_reg(memory mem, vec src) %{ + match(Set mem (StoreVector mem (VectorCastF2HF src))); + format %{ "vcvtps2ph $mem,$src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this, $src); + __ vcvtps2ph($mem$$Address, $src$$XMMRegister, 0x04, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct convHF2F_reg_reg(regF dst, rRegI src) %{ match(Set dst (ConvHF2F src)); format %{ "vcvtph2ps $dst,$src" %} @@ -3683,6 +3715,27 @@ instruct convHF2F_reg_reg(regF dst, rRegI src) %{ ins_pipe( pipe_slow ); %} +instruct vconvHF2F_reg_mem(vec dst, memory mem) %{ + match(Set dst (VectorCastHF2F (LoadVector mem))); + format %{ "vcvtph2ps $dst,$mem" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vcvtph2ps($dst$$XMMRegister, $mem$$Address, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vconvHF2F(vec dst, vec src) %{ + match(Set dst (VectorCastHF2F src)); + ins_cost(125); + format %{ "vector_conv_HF2F $dst,$src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vcvtph2ps($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + // ---------------------------------------- VectorReinterpret ------------------------------------ instruct reinterpret_mask(kReg dst) %{ predicate(n->bottom_type()->isa_vectmask() && @@ -7993,169 +8046,70 @@ instruct vabsnegD(vec dst, vec src) %{ //------------------------------------- VectorTest -------------------------------------------- #ifdef _LP64 -instruct vptest_alltrue_lt16(rRegI dst, legVec src1, legVec src2, legVec vtmp1, legVec vtmp2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)) < 16 && - static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP vtmp1, TEMP vtmp2, KILL cr); - format %{ "vptest_alltrue_lt16 $dst,$src1, $src2\t! using $vtmp1, $vtmp2 and $cr as TEMP" %} +instruct vptest_lt16(rFlagsRegU cr, legVec src1, legVec src2, legVec vtmp) %{ + predicate(Matcher::vector_length_in_bytes(n->in(1)) < 16); + match(Set cr (VectorTest src1 src2)); + effect(TEMP vtmp); + format %{ "vptest_lt16 $src1, $src2\t! using $vtmp as TEMP" %} ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src1); int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::overflow, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp1$$XMMRegister, $vtmp2$$XMMRegister); - __ setb(Assembler::carrySet, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); + __ vectortest(bt, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister, vlen); %} ins_pipe( pipe_slow ); %} -instruct vptest_alltrue_ge16(rRegI dst, legVec src1, legVec src2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)) < 64 && - static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2 )); - effect(KILL cr); - format %{ "vptest_alltrue_ge16 $dst,$src1, $src2\t! using $cr as TEMP" %} +instruct vptest_ge16(rFlagsRegU cr, legVec src1, legVec src2) %{ + predicate(Matcher::vector_length_in_bytes(n->in(1)) >= 16); + match(Set cr (VectorTest src1 src2)); + format %{ "vptest_ge16 $src1, $src2\n\t" %} ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src1); int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::overflow, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); - __ setb(Assembler::carrySet, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); + __ vectortest(bt, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, vlen); %} ins_pipe( pipe_slow ); %} -instruct vptest_alltrue_lt8_evex(rRegI dst, kReg src1, kReg src2, kReg kscratch, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::overflow && - n->in(1)->bottom_type()->isa_vectmask() && - Matcher::vector_length(n->in(1)) < 8); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr, TEMP kscratch); - format %{ "vptest_alltrue_lt8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - uint masklen = Matcher::vector_length(this, $src1); - __ alltrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister, $kscratch$$KRegister); - %} - ins_pipe( pipe_slow ); -%} - - -instruct vptest_alltrue_ge8_evex(rRegI dst, kReg src1, kReg src2, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::overflow && - n->in(1)->bottom_type()->isa_vectmask() && - Matcher::vector_length(n->in(1)) >= 8); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vptest_alltrue_ge8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} +instruct ktest_alltrue_le8(rFlagsRegU cr, kReg src1, kReg src2, rRegI tmp) %{ + predicate((Matcher::vector_length(n->in(1)) < 8 || + (Matcher::vector_length(n->in(1)) == 8 && !VM_Version::supports_avx512dq())) && + static_cast(n)->get_predicate() == BoolTest::overflow); + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "ktest_alltrue_le8 $src1, $src2\t! using $tmp as TEMP" %} ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); uint masklen = Matcher::vector_length(this, $src1); - __ alltrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister, knoreg); + __ kmovwl($tmp$$Register, $src1$$KRegister); + __ andl($tmp$$Register, (1 << masklen) - 1); + __ cmpl($tmp$$Register, (1 << masklen) - 1); %} ins_pipe( pipe_slow ); %} - -instruct vptest_anytrue_lt16(rRegI dst, legVec src1, legVec src2, legVec vtmp, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)) < 16 && +instruct ktest_anytrue_le8(rFlagsRegU cr, kReg src1, kReg src2, rRegI tmp) %{ + predicate((Matcher::vector_length(n->in(1)) < 8 || + (Matcher::vector_length(n->in(1)) == 8 && !VM_Version::supports_avx512dq())) && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP vtmp, KILL cr); - format %{ "vptest_anytrue_lt16 $dst,$src1,$src2\t! using $vtmp, $cr as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister); - __ setb(Assembler::notZero, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); - %} - ins_pipe( pipe_slow ); -%} - -instruct vptest_anytrue_ge16(rRegI dst, legVec src1, legVec src2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)) < 64 && - static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(KILL cr); - format %{ "vptest_anytrue_ge16 $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); - __ setb(Assembler::notZero, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); - %} - ins_pipe( pipe_slow ); -%} - -instruct vptest_anytrue_evex(rRegI dst, kReg src1, kReg src2, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vptest_anytrue_lt8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - uint masklen = Matcher::vector_length(this, $src1); - __ anytrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct cmpvptest_anytrue_lt16(rFlagsReg cr, legVec src1, legVec src2, immI_0 zero, legVec vtmp) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) < 16 && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - effect(TEMP vtmp); - format %{ "cmpvptest_anytrue_lt16 $src1,$src2\t! using $vtmp as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct cmpvptest_anytrue_ge16(rFlagsReg cr, legVec src1, legVec src2, immI_0 zero) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) < 64 && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - format %{ "cmpvptest_anytrue_ge16 $src1,$src2\t!" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "ktest_anytrue_le8 $src1, $src2\t! using $tmp as TEMP" %} ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); + uint masklen = Matcher::vector_length(this, $src1); + __ kmovwl($tmp$$Register, $src1$$KRegister); + __ andl($tmp$$Register, (1 << masklen) - 1); %} ins_pipe( pipe_slow ); %} -instruct cmpvptest_anytrue_evex(rFlagsReg cr, kReg src1, kReg src2, immI_0 zero) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - format %{ "cmpvptest_anytrue_evex $src1,$src2\t!" %} +instruct ktest_ge8(rFlagsRegU cr, kReg src1, kReg src2) %{ + predicate(Matcher::vector_length(n->in(1)) >= 16 || + (Matcher::vector_length(n->in(1)) == 8 && VM_Version::supports_avx512dq())); + match(Set cr (VectorTest src1 src2)); + format %{ "ktest_ge8 $src1, $src2\n\t" %} ins_encode %{ uint masklen = Matcher::vector_length(this, $src1); - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - masklen = masklen < 8 ? 8 : masklen; - __ ktest(masklen, $src1$$KRegister, $src2$$KRegister); + __ kortest(masklen, $src1$$KRegister, $src1$$KRegister); %} ins_pipe( pipe_slow ); %} @@ -8875,12 +8829,6 @@ instruct vpopcount_integral_reg_evex(vec dst, vec src) %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); __ vector_popcount_integral_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, k0, true, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (opcode == Op_PopCountVL && Matcher::vector_element_basic_type(this) == T_INT) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -8911,18 +8859,6 @@ instruct vpopcount_avx_reg(vec dst, vec src, vec xtmp1, vec xtmp2, rRegP rtmp) % BasicType bt = Matcher::vector_element_basic_type(this, $src); __ vector_popcount_integral(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (opcode == Op_PopCountVL && Matcher::vector_element_basic_type(this) == T_INT) { - if (VM_Version::supports_avx512vl()) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } else { - assert(VM_Version::supports_avx2(), ""); - __ vpshufd($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - } - } %} ins_pipe( pipe_slow ); %} @@ -8939,15 +8875,8 @@ instruct vcount_trailing_zeros_reg_evex(vec dst, vec src, vec xtmp, rRegP rtmp) ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_trailing_zeros_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, $xtmp$$XMMRegister, k0, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountTrailingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (bt == T_LONG && rbt == T_INT) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -8993,17 +8922,8 @@ instruct vcount_trailing_zeros_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, v ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_trailing_zeros_avx(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (bt == T_LONG && rbt == T_INT) { - assert(VM_Version::supports_avx2(), ""); - __ vpshufd($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -9408,15 +9328,8 @@ instruct vcount_leading_zeros_IL_reg_evex(vec dst, vec src) %{ ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_leading_zeros_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, k0, noreg, true, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountLeadingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (rbt == T_INT && bt == T_LONG) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -9491,15 +9404,8 @@ instruct vcount_leading_zeros_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, ve ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_leading_zeros_avx(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountLeadingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (rbt == T_INT && bt == T_LONG) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 017ce230ba4..979494e4cb1 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -708,7 +708,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, thread, true /* at_return */, true /* in_nmethod */); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 995ed35de0c..16cd035ac79 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -889,7 +889,7 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { } if (C->stub_function() != NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { st->print("\n\t"); - st->print("cmpl [r15_thread + #disarmed_offset], #disarmed_value\t"); + st->print("cmpl [r15_thread + #disarmed_guard_value_offset], #disarmed_guard_value\t"); st->print("\n\t"); st->print("je fast_entry\t"); st->print("\n\t"); @@ -1020,7 +1020,9 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, r15_thread, true /* at_return */, true /* in_nmethod */); @@ -2164,13 +2166,19 @@ encode %{ // determine who we intended to call. MacroAssembler _masm(&cbuf); cbuf.set_insts_mark(); - $$$emit8$primary; if (!_method) { + $$$emit8$primary; emit_d32_reloc(cbuf, (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4), runtime_call_Relocation::spec(), RELOC_DISP32); + } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) { + // The NOP here is purely to ensure that eliding a call to + // JVM_EnsureMaterializedForStackWalk doesn't change the code size. + __ addr_nop_5(); + __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); } else { + $$$emit8$primary; int method_index = resolved_method_index(cbuf); RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) : static_call_Relocation::spec(method_index); @@ -6072,6 +6080,7 @@ instruct storeL(memory mem, rRegL src) // Store Pointer instruct storeP(memory mem, any_RegP src) %{ + predicate(n->as_Store()->barrier_data() == 0); match(Set mem (StoreP mem src)); ins_cost(125); // XXX @@ -6084,7 +6093,7 @@ instruct storeP(memory mem, any_RegP src) instruct storeImmP0(memory mem, immP0 zero) %{ - predicate(UseCompressedOops && (CompressedOops::base() == NULL)); + predicate(UseCompressedOops && (CompressedOops::base() == NULL) && n->as_Store()->barrier_data() == 0); match(Set mem (StoreP mem zero)); ins_cost(125); // XXX @@ -6098,6 +6107,7 @@ instruct storeImmP0(memory mem, immP0 zero) // Store NULL Pointer, mark word, or other simple pointer constant. instruct storeImmP(memory mem, immP31 src) %{ + predicate(n->as_Store()->barrier_data() == 0); match(Set mem (StoreP mem src)); ins_cost(150); // XXX diff --git a/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp b/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp index 69d77500fa7..7de24a461c9 100644 --- a/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp +++ b/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/zero/downcallLinker_zero.cpp b/src/hotspot/cpu/zero/downcallLinker_zero.cpp index 3fc43c5031e..3f1241970f2 100644 --- a/src/hotspot/cpu/zero/downcallLinker_zero.cpp +++ b/src/hotspot/cpu/zero/downcallLinker_zero.cpp @@ -28,9 +28,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/zero/foreignGlobals_zero.cpp b/src/hotspot/cpu/zero/foreignGlobals_zero.cpp index 21f6e9fd464..7c35da7e3e0 100644 --- a/src/hotspot/cpu/zero/foreignGlobals_zero.cpp +++ b/src/hotspot/cpu/zero/foreignGlobals_zero.cpp @@ -33,24 +33,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp b/src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp index 1ac11ec3a4b..90f971a3152 100644 --- a/src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp +++ b/src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp @@ -30,15 +30,11 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { ShouldNotReachHere(); } -void BarrierSetNMethod::arm(nmethod* nm, int value) { +void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) { ShouldNotReachHere(); } -void BarrierSetNMethod::disarm(nmethod* nm) { +int BarrierSetNMethod::guard_value(nmethod* nm) { ShouldNotReachHere(); -} - -bool BarrierSetNMethod::is_armed(nmethod* nm) { - ShouldNotReachHere(); - return false; + return -1; } diff --git a/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp b/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp index 64eb4e00ced..d9f16caca1e 100644 --- a/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp +++ b/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/zero/stubGenerator_zero.cpp b/src/hotspot/cpu/zero/stubGenerator_zero.cpp index 80e55d9c8e4..4fe19588133 100644 --- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp +++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp @@ -191,12 +191,9 @@ class StubGenerator: public StubCodeGenerator { // atomic calls StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_xchg_long_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_add_long_entry = ShouldNotCallThisStub(); StubRoutines::_fence_entry = ShouldNotCallThisStub(); } diff --git a/src/hotspot/cpu/zero/vmstorage_zero.hpp b/src/hotspot/cpu/zero/vmstorage_zero.hpp new file mode 100644 index 00000000000..7536a6227e9 --- /dev/null +++ b/src/hotspot/cpu/zero/vmstorage_zero.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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_ZERO_VMSTORAGE_ZERO_INLINE_HPP +#define CPU_ZERO_VMSTORAGE_ZERO_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + + +#endif // CPU_ZERO_VMSTORAGE_ZERO_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index ff7eefa7f7d..f11ddabeacf 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1872,7 +1872,7 @@ int os::numa_get_group_id_for_address(const void* address) { return 0; } -bool os::get_page_info(char *start, page_info* info) { +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) { return false; } diff --git a/src/hotspot/os/bsd/attachListener_bsd.cpp b/src/hotspot/os/bsd/attachListener_bsd.cpp index 7999210bc3e..779b439d16b 100644 --- a/src/hotspot/os/bsd/attachListener_bsd.cpp +++ b/src/hotspot/os/bsd/attachListener_bsd.cpp @@ -248,7 +248,7 @@ int BsdAttachListener::init() { // BsdAttachOperation* BsdAttachListener::read_request(int s) { char ver_str[8]; - sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); + size_t ver_str_len = os::snprintf_checked(ver_str, sizeof(ver_str), "%d", ATTACH_PROTOCOL_VER); // The request is a sequence of strings so we first figure out the // expected count and the maximum possible length of the request. @@ -288,11 +288,11 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) { // The first string is so check it now to // check for protocol mismatch if (str_count == 1) { - if ((strlen(buf) != strlen(ver_str)) || + if ((strlen(buf) != ver_str_len) || (atoi(buf) != ATTACH_PROTOCOL_VER)) { char msg[32]; - sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); - write_fully(s, msg, strlen(msg)); + int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", ATTACH_ERROR_BADVERSION); + write_fully(s, msg, msg_len); return NULL; } } @@ -411,8 +411,8 @@ void BsdAttachOperation::complete(jint result, bufferedStream* st) { // write operation result char msg[32]; - sprintf(msg, "%d\n", result); - int rc = BsdAttachListener::write_fully(this->socket(), msg, strlen(msg)); + int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", result); + int rc = BsdAttachListener::write_fully(this->socket(), msg, msg_len); // write any result data if (rc == 0) { diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index a0cf536134e..439d1eee73c 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -320,7 +320,7 @@ void os::init_system_properties_values() { #ifndef __APPLE__ - // Buffer that fits several sprintfs. + // Buffer that fits several snprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize = @@ -376,17 +376,16 @@ void os::init_system_properties_values() { const char *v_colon = ":"; if (v == NULL) { v = ""; v_colon = ""; } // That's +1 for the colon and +1 for the trailing '\0'. - char *ld_library_path = NEW_C_HEAP_ARRAY(char, - strlen(v) + 1 + - sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1, - mtInternal); - sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch); + const size_t ld_library_path_size = strlen(v) + 1 + sizeof(SYS_EXT_DIR) + + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1; + char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal); + os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch); Arguments::set_library_path(ld_library_path); FREE_C_HEAP_ARRAY(char, ld_library_path); } // Extensions directories. - sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home()); + os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home()); Arguments::set_ext_dirs(buf); FREE_C_HEAP_ARRAY(char, buf); @@ -401,7 +400,7 @@ void os::init_system_properties_values() { size_t system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + sizeof(SYS_EXTENSIONS_DIRS); - // Buffer that fits several sprintfs. + // Buffer that fits several snprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize = @@ -471,11 +470,9 @@ void os::init_system_properties_values() { // could cause a change in behavior, but Apple's Java6 behavior // can be achieved by putting "." at the beginning of the // JAVA_LIBRARY_PATH environment variable. - char *ld_library_path = NEW_C_HEAP_ARRAY(char, - strlen(v) + 1 + strlen(l) + 1 + - system_ext_size + 3, - mtInternal); - sprintf(ld_library_path, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.", + const size_t ld_library_path_size = strlen(v) + 1 + strlen(l) + 1 + system_ext_size + 3; + char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal); + os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.", v, v_colon, l, l_colon, user_home_dir); Arguments::set_library_path(ld_library_path); FREE_C_HEAP_ARRAY(char, ld_library_path); @@ -486,7 +483,7 @@ void os::init_system_properties_values() { // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator (so actually one byte more // than necessary is allocated). - sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, + os::snprintf_checked(buf, bufsize, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home()); Arguments::set_ext_dirs(buf); @@ -1578,7 +1575,7 @@ int os::numa_get_group_id_for_address(const void* address) { return 0; } -bool os::get_page_info(char *start, page_info* info) { +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) { return false; } diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 91456b3d0e1..991f25b7172 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -78,71 +78,83 @@ class CgroupController: public CHeapObj { PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED +// Parses a subsystem's file, looking for a matching line. +// If key is null, then the first line will be matched with scan_fmt. +// If key isn't null, then each line will be matched, looking for something that matches "$key $scan_fmt". +// The matching value will be assigned to returnval. +// scan_fmt uses scanf() syntax. +// Return value: 0 on match, OSCONTAINER_ERROR on error. template int subsystem_file_line_contents(CgroupController* c, const char *filename, - const char *matchline, + const char *key, const char *scan_fmt, T returnval) { - FILE *fp = NULL; - char *p; - char file[MAXPATHLEN+1]; - char buf[MAXPATHLEN+1]; - char discard[MAXPATHLEN+1]; - bool found_match = false; + if (c == nullptr) { + log_debug(os, container)("subsystem_file_line_contents: CgroupController* is nullptr"); + return OSCONTAINER_ERROR; + } + if (c->subsystem_path() == nullptr) { + log_debug(os, container)("subsystem_file_line_contents: subsystem path is nullptr"); + return OSCONTAINER_ERROR; + } + + stringStream file_path; + file_path.print_raw(c->subsystem_path()); + file_path.print_raw(filename); - if (c == NULL) { - log_debug(os, container)("subsystem_file_line_contents: CgroupController* is NULL"); + if (file_path.size() > (MAXPATHLEN-1)) { + log_debug(os, container)("File path too long %s, %s", file_path.base(), filename); return OSCONTAINER_ERROR; } - if (c->subsystem_path() == NULL) { - log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL"); + const char* absolute_path = file_path.freeze(); + log_trace(os, container)("Path to %s is %s", filename, absolute_path); + + FILE* fp = os::fopen(absolute_path, "r"); + if (fp == nullptr) { + log_debug(os, container)("Open of file %s failed, %s", absolute_path, os::strerror(errno)); return OSCONTAINER_ERROR; } - strncpy(file, c->subsystem_path(), MAXPATHLEN); - file[MAXPATHLEN-1] = '\0'; - int filelen = strlen(file); - if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) { - log_debug(os, container)("File path too long %s, %s", file, filename); + const int buf_len = MAXPATHLEN+1; + char buf[buf_len]; + char* line = fgets(buf, buf_len, fp); + if (line == nullptr) { + log_debug(os, container)("Empty file %s", absolute_path); + fclose(fp); return OSCONTAINER_ERROR; } - strncat(file, filename, MAXPATHLEN-filelen); - log_trace(os, container)("Path to %s is %s", filename, file); - fp = os::fopen(file, "r"); - if (fp != NULL) { - int err = 0; - while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) { - found_match = false; - if (matchline == NULL) { - // single-line file case - int matched = sscanf(p, scan_fmt, returnval); - found_match = (matched == 1); - } else { - // multi-line file case - if (strstr(p, matchline) != NULL) { - // discard matchline string prefix - int matched = sscanf(p, scan_fmt, discard, returnval); - found_match = (matched == 2); - } else { - continue; // substring not found + + bool found_match = false; + if (key == nullptr) { + // File consists of a single line according to caller, with only a value + int matched = sscanf(line, scan_fmt, returnval); + found_match = matched == 1; + } else { + // File consists of multiple lines in a "key value" + // fashion, we have to find the key. + const int key_len = strlen(key); + for (; line != nullptr; line = fgets(buf, buf_len, fp)) { + char* key_substr = strstr(line, key); + char after_key = line[key_len]; + if (key_substr == line + && isspace(after_key) != 0 + && after_key != '\n') { + // Skip key, skip space + const char* value_substr = line + key_len + 1; + int matched = sscanf(value_substr, scan_fmt, returnval); + found_match = matched == 1; + if (found_match) { + break; } } - if (found_match) { - fclose(fp); - return 0; - } else { - err = 1; - log_debug(os, container)("Type %s not found in file %s", scan_fmt, file); - } } - if (err == 0) { - log_debug(os, container)("Empty file %s", file); - } - } else { - log_debug(os, container)("Open of file %s failed, %s", file, os::strerror(errno)); } - if (fp != NULL) - fclose(fp); + fclose(fp); + if (found_match) { + return 0; + } + log_debug(os, container)("Type %s (key == %s) not found in file %s", scan_fmt, + (key == nullptr ? "null" : key), absolute_path); return OSCONTAINER_ERROR; } PRAGMA_DIAG_POP diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index e62dcf4f759..cfa8f516e3e 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -96,10 +96,8 @@ jlong CgroupV1Subsystem::read_memory_limit_in_bytes() { log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); CgroupV1MemoryController* mem_controller = reinterpret_cast(_memory->controller()); if (mem_controller->is_hierarchical()) { - const char* matchline = "hierarchical_memory_limit"; - const char* format = "%s " JULONG_FORMAT; - GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline, - "Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit) + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", "hierarchical_memory_limit", + "Hierarchical Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, hier_memlimit) if (hier_memlimit >= os::Linux::physical_memory()) { log_trace(os, container)("Hierarchical Memory Limit is: Unlimited"); } else { @@ -123,9 +121,8 @@ jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() { CgroupV1MemoryController* mem_controller = reinterpret_cast(_memory->controller()); if (mem_controller->is_hierarchical()) { const char* matchline = "hierarchical_memsw_limit"; - const char* format = "%s " JULONG_FORMAT; GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline, - "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memswlimit) + "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, JULONG_FORMAT, hier_memswlimit) if (hier_memswlimit >= host_total_memsw) { log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited"); } else { @@ -133,7 +130,7 @@ jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() { if (swappiness == 0) { const char* matchmemline = "hierarchical_memory_limit"; GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchmemline, - "Hierarchical Memory Limit is : " JULONG_FORMAT, format, hier_memlimit) + "Hierarchical Memory Limit is : " JULONG_FORMAT, JULONG_FORMAT, hier_memlimit) log_trace(os, container)("Memory and Swap Limit has been reset to " JULONG_FORMAT " because swappiness is 0", hier_memlimit); return (jlong)hier_memlimit; } @@ -286,10 +283,7 @@ int CgroupV1Subsystem::cpu_shares() { char* CgroupV1Subsystem::pids_max_val() { GET_CONTAINER_INFO_CPTR(cptr, _pids, "/pids.max", - "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); - if (pidsmax == NULL) { - return NULL; - } + "Maximum number of tasks is: %s", "%1023s", pidsmax, 1024); return os::strdup(pidsmax); } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 25ab8f55f38..190b12438f6 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -92,27 +92,18 @@ int CgroupV2Subsystem::cpu_quota() { char * CgroupV2Subsystem::cpu_cpuset_cpus() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.cpus", "cpuset.cpus is: %s", "%1023s", cpus, 1024); - if (cpus == NULL) { - return NULL; - } return os::strdup(cpus); } char* CgroupV2Subsystem::cpu_quota_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpu.max", - "Raw value for CPU quota is: %s", "%s %*d", quota, 1024); - if (quota == NULL) { - return NULL; - } + "Raw value for CPU quota is: %s", "%1023s %*d", quota, 1024); return os::strdup(quota); } char * CgroupV2Subsystem::cpu_cpuset_memory_nodes() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.mems", "cpuset.mems is: %s", "%1023s", mems, 1024); - if (mems == NULL) { - return NULL; - } return os::strdup(mems); } @@ -150,10 +141,7 @@ jlong CgroupV2Subsystem::memory_max_usage_in_bytes() { char* CgroupV2Subsystem::mem_soft_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", - "Memory Soft Limit is: %s", "%s", mem_soft_limit_str, 1024); - if (mem_soft_limit_str == NULL) { - return NULL; - } + "Memory Soft Limit is: %s", "%1023s", mem_soft_limit_str, 1024); return os::strdup(mem_soft_limit_str); } @@ -175,20 +163,14 @@ jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() { char* CgroupV2Subsystem::mem_swp_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.max", - "Memory and Swap Limit is: %s", "%s", mem_swp_limit_str, 1024); - if (mem_swp_limit_str == NULL) { - return NULL; - } + "Memory and Swap Limit is: %s", "%1023s", mem_swp_limit_str, 1024); return os::strdup(mem_swp_limit_str); } // memory.swap.current : total amount of swap currently used by the cgroup and its descendants char* CgroupV2Subsystem::mem_swp_current_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.current", - "Swap currently used is: %s", "%s", mem_swp_current_str, 1024); - if (mem_swp_current_str == NULL) { - return NULL; - } + "Swap currently used is: %s", "%1023s", mem_swp_current_str, 1024); return os::strdup(mem_swp_current_str); } @@ -215,10 +197,7 @@ jlong CgroupV2Subsystem::read_memory_limit_in_bytes() { char* CgroupV2Subsystem::mem_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max", - "Raw value for memory limit is: %s", "%s", mem_limit_str, 1024); - if (mem_limit_str == NULL) { - return NULL; - } + "Raw value for memory limit is: %s", "%1023s", mem_limit_str, 1024); return os::strdup(mem_limit_str); } @@ -244,10 +223,7 @@ char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { char* CgroupV2Subsystem::pids_max_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/pids.max", - "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); - if (pidsmax == NULL) { - return NULL; - } + "Maximum number of tasks is: %s", "%1023s", pidsmax, 1024); return os::strdup(pidsmax); } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 7d9636d250a..0d261adf93c 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2777,6 +2777,11 @@ int os::numa_get_group_id_for_address(const void* address) { return id; } +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) { + void** pages = const_cast(addresses); + return os::Linux::numa_move_pages(0, count, pages, NULL, lgrp_ids, 0) == 0; +} + int os::Linux::get_existing_num_nodes() { int node; int highest_node_number = Linux::numa_max_node(); @@ -2807,10 +2812,6 @@ size_t os::numa_get_leaf_groups(int *ids, size_t size) { return i; } -bool os::get_page_info(char *start, page_info* info) { - return false; -} - char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { return end; diff --git a/src/hotspot/os/posix/mutex_posix.hpp b/src/hotspot/os/posix/mutex_posix.hpp index 869ac7de553..7acd741973f 100644 --- a/src/hotspot/os/posix/mutex_posix.hpp +++ b/src/hotspot/os/posix/mutex_posix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -133,7 +133,7 @@ class PlatformMonitor : public PlatformMutex { NONCOPYABLE(PlatformMonitor); public: - int wait(jlong millis); + int wait(uint64_t millis); void notify(); void notify_all(); }; diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index ef0f77157d4..7a85a2ccb86 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1869,17 +1869,17 @@ PlatformMonitor::~PlatformMonitor() { #endif // PLATFORM_MONITOR_IMPL_INDIRECT // Must already be locked -int PlatformMonitor::wait(jlong millis) { - assert(millis >= 0, "negative timeout"); +int PlatformMonitor::wait(uint64_t millis) { if (millis > 0) { struct timespec abst; // We have to watch for overflow when converting millis to nanos, // but if millis is that large then we will end up limiting to - // MAX_SECS anyway, so just do that here. + // MAX_SECS anyway, so just do that here. This also handles values + // larger than int64_t max. if (millis / MILLIUNITS > MAX_SECS) { - millis = jlong(MAX_SECS) * MILLIUNITS; + millis = uint64_t(MAX_SECS) * MILLIUNITS; } - to_abstime(&abst, millis_to_nanos(millis), false, false); + to_abstime(&abst, millis_to_nanos(int64_t(millis)), false, false); int ret = OS_TIMEOUT; int status = pthread_cond_timedwait(cond(), mutex(), &abst); diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index c4cdb4c74f5..598955cbdfb 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1205,7 +1205,10 @@ static void mmap_attach_shared(int vmid, char** addr, size_t* sizep, TRAPS) { FREE_C_HEAP_ARRAY(char, dirname); FREE_C_HEAP_ARRAY(char, filename); - if (fd == OS_ERR || HAS_PENDING_EXCEPTION) { + if (HAS_PENDING_EXCEPTION) { + assert(fd == OS_ERR, "open_sharedmem_file always return OS_ERR on exceptions"); + } + if (fd == OS_ERR) { return; } diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 1c634130be0..464e0a483be 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -639,7 +639,7 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info, // Call platform dependent signal handler. if (!signal_was_handled) { - JavaThread* const jt = (t != NULL && t->is_Java_thread()) ? (JavaThread*) t : NULL; + JavaThread* const jt = (t != NULL && t->is_Java_thread()) ? JavaThread::cast(t) : NULL; signal_was_handled = PosixSignals::pd_hotspot_signal_handler(sig, info, uc, jt); } diff --git a/src/hotspot/os/windows/mutex_windows.hpp b/src/hotspot/os/windows/mutex_windows.hpp index 6785d3102ac..5235308bb06 100644 --- a/src/hotspot/os/windows/mutex_windows.hpp +++ b/src/hotspot/os/windows/mutex_windows.hpp @@ -56,7 +56,7 @@ class PlatformMonitor : public PlatformMutex { public: PlatformMonitor(); ~PlatformMonitor(); - int wait(jlong millis); + int wait(uint64_t millis); void notify(); void notify_all(); }; diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 3262a9ddc8b..a027587f5f7 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -510,8 +510,10 @@ struct tm* os::gmtime_pd(const time_t* clock, struct tm* res) { JNIEXPORT LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo); -// Thread start routine for all newly created threads -static unsigned __stdcall thread_native_entry(Thread* thread) { +// Thread start routine for all newly created threads. +// Called with the associated Thread* as the argument. +unsigned __stdcall os::win32::thread_native_entry(void* t) { + Thread* thread = static_cast(t); thread->record_stack_base_and_size(); thread->initialize_thread_current(); @@ -744,7 +746,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, - (unsigned (__stdcall *)(void*)) thread_native_entry, + &os::win32::thread_native_entry, thread, initflag, &thread_id); @@ -1886,6 +1888,10 @@ void os::get_summary_cpu_info(char* buf, size_t buflen) { status = RegQueryValueEx(key, "ProcessorNameString", NULL, NULL, (byte*)buf, &size); if (status != ERROR_SUCCESS) { strncpy(buf, "## __CPU__", buflen); + } else { + if (size < buflen) { + buf[size] = '\0'; + } } RegCloseKey(key); } else { @@ -3721,7 +3727,7 @@ int os::numa_get_group_id_for_address(const void* address) { return 0; } -bool os::get_page_info(char *start, page_info* info) { +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) { return false; } @@ -5356,11 +5362,14 @@ void Parker::unpark() { // Platform Monitor implementation // Must already be locked -int PlatformMonitor::wait(jlong millis) { - assert(millis >= 0, "negative timeout"); +int PlatformMonitor::wait(uint64_t millis) { int ret = OS_TIMEOUT; + // The timeout parameter for SleepConditionVariableCS is a DWORD + if (millis > UINT_MAX) { + millis = UINT_MAX; + } int status = SleepConditionVariableCS(&_cond, &_mutex, - millis == 0 ? INFINITE : millis); + millis == 0 ? INFINITE : (DWORD)millis); if (status != 0) { ret = OS_OK; } diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 94d7c3c5e2d..197797078d7 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -36,7 +36,6 @@ typedef void (*signal_handler_t)(int); class os::win32 { friend class os; - friend unsigned __stdcall thread_native_entry(Thread*); protected: static int _processor_type; @@ -70,6 +69,10 @@ class os::win32 { static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen); private: + // The handler passed to _beginthreadex(). + // Called with the associated Thread* as the argument. + static unsigned __stdcall thread_native_entry(void*); + enum Ept { EPT_THREAD, EPT_PROCESS, EPT_PROCESS_DIE }; // Wrapper around _endthreadex(), exit() and _exit() static int exit_process_or_thread(Ept what, int exit_code); diff --git a/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp index 10352994df6..38a5547a553 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp @@ -50,13 +50,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -75,11 +72,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -98,4 +95,3 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } void JavaThread::cache_global_variables() { } - diff --git a/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp index 6af1fee4f8b..8e97fa6b5c1 100644 --- a/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp @@ -49,15 +49,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - - assert(this->is_Java_thread(), "must be JavaThread"); - - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than CONTEXT info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -71,11 +66,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_frame.sp(), NULL, ret_frame.pc()); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -88,7 +83,6 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) *fr_addr = ret_frame; return true; } - // nothing else to try return false; } diff --git a/src/hotspot/share/adlc/adlc.hpp b/src/hotspot/share/adlc/adlc.hpp index 555029fdbb6..8812066bafa 100644 --- a/src/hotspot/share/adlc/adlc.hpp +++ b/src/hotspot/share/adlc/adlc.hpp @@ -100,4 +100,8 @@ typedef unsigned int uintptr_t; // it everywhere it needs to be available. extern ArchDesc* globalAD; +// Performs snprintf and asserts the result is non-negative (so there was not +// an encoding error) and that the output was not truncated. +extern int snprintf_checked(char* buf, size_t len, const char* fmt, ...); + #endif // SHARE_ADLC_ADLC_HPP diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index adf5b731589..8190f82a050 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -211,8 +211,9 @@ void ADLParser::instr_parse(void) { return; } assert(match_rules_cnt < 100," too many match rule clones"); - char* buf = (char*) AdlAllocateHeap(strlen(instr->_ident) + 4); - sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); + const size_t buf_size = strlen(instr->_ident) + 4; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "%s_%d", instr->_ident, match_rules_cnt++); rule->_result = buf; // Check for commutative operations with tree operands. matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); @@ -2876,8 +2877,9 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__ins_encode_"; - char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); - sprintf(ec_name, "%s%s", prefix, inst._ident); + const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1; + char* ec_name = (char*) AdlAllocateHeap(ec_name_size); + snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass* encoding = _AD._encode->add_EncClass(ec_name); @@ -3347,8 +3349,9 @@ void ADLParser::constant_parse(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__constant_"; - char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); - sprintf(ec_name, "%s%s", prefix, inst._ident); + const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1; + char* ec_name = (char*) AdlAllocateHeap(ec_name_size); + snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass* encoding = _AD._encode->add_EncClass(ec_name); @@ -4667,8 +4670,9 @@ char *ADLParser::get_ident_or_literal_constant(const char* description) { // Grab a constant expression. param = get_paren_expr(description); if (param[0] != '(') { - char* buf = (char*) AdlAllocateHeap(strlen(param) + 3); - sprintf(buf, "(%s)", param); + const size_t buf_size = strlen(param) + 3; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "(%s)", param); param = buf; } assert(is_literal_constant(param), @@ -5275,8 +5279,9 @@ void ADLParser::next_line() { char* ADLParser::get_line_string(int linenum) { const char* file = _AD._ADL_file._name; int line = linenum ? linenum : this->linenum(); - char* location = (char *)AdlAllocateHeap(strlen(file) + 100); - sprintf(location, "\n#line %d \"%s\"\n", line, file); + const size_t location_size = strlen(file) + 100; + char* location = (char *)AdlAllocateHeap(location_size); + snprintf_checked(location, location_size, "\n#line %d \"%s\"\n", line, file); return location; } diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp index a437dd29c75..890b266d58d 100644 --- a/src/hotspot/share/adlc/archDesc.cpp +++ b/src/hotspot/share/adlc/archDesc.cpp @@ -815,7 +815,7 @@ static const char *getRegMask(const char *reg_class_name) { const char *mask = "_mask"; int length = (int)strlen(rc_name) + (int)strlen(mask) + 5; char *regMask = new char[length]; - sprintf(regMask,"%s%s()", rc_name, mask); + snprintf_checked(regMask, length, "%s%s()", rc_name, mask); delete[] rc_name; return regMask; } @@ -908,7 +908,7 @@ char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) { const char *stack_or = "STACK_OR_"; int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1; char *result = new char[length]; - sprintf(result,"%s%s", stack_or, reg_mask_name); + snprintf_checked(result, length, "%s%s", stack_or, reg_mask_name); return result; } diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp index 36cba614878..e3a92ec1e5b 100644 --- a/src/hotspot/share/adlc/dfa.cpp +++ b/src/hotspot/share/adlc/dfa.cpp @@ -212,13 +212,13 @@ Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, Produc Expr *c = new Expr("0"); if (mList._lchild) { // If left child, add it in const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild); - sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper); + snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[0]->_cost[%s]", lchild_to_upper); c->add(Expr::buffer()); delete[] lchild_to_upper; } if (mList._rchild) { // If right child, add it in const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild); - sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper); + snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[1]->_cost[%s]", rchild_to_upper); c->add(Expr::buffer()); delete[] rchild_to_upper; } @@ -757,7 +757,7 @@ const char *Expr::compute_expr(const Expr *c1, const Expr *c2) { snprintf(string_buffer, STRING_BUFFER_LENGTH, "%s", c2->_expr); } else { - sprintf( string_buffer, "0"); + snprintf_checked(string_buffer, STRING_BUFFER_LENGTH, "0"); } string_buffer[STRING_BUFFER_LENGTH - 1] = '\0'; char *cost = strdup(string_buffer); diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index d09c6a5ca92..d6d13478339 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -25,6 +25,8 @@ // FORMS.CPP - Definitions for ADL Parser Forms Classes #include "adlc.hpp" +#define remaining_buflen(buffer, position) (sizeof(buffer) - ((position) - (buffer))) + //==============================Instructions=================================== //------------------------------InstructForm----------------------------------- InstructForm::InstructForm(const char *id, bool ideal_only) @@ -1533,7 +1535,7 @@ Predicate *InstructForm::build_predicate() { s += strlen(s); } // Add predicate to working buffer - sprintf(s,"/*%s*/(",(char*)i._key); + snprintf_checked(s, remaining_buflen(buf, s), "/*%s*/(",(char*)i._key); s += strlen(s); mnode->build_instr_pred(s,(char*)i._key, 0, path_bitmask, 0); s += strlen(s); @@ -3472,7 +3474,7 @@ void MatchNode::build_internalop( ) { _rChild->_internalop : _rChild->_opType) : ""; len += (int)strlen(lstr) + (int)strlen(rstr); subtree = (char *)AdlAllocateHeap(len); - sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr); + snprintf_checked(subtree, len, "_%s_%s_%s", _opType, lstr, rstr); // Hash the subtree string in _internalOps; if a name exists, use it iop = (char *)_AD._internalOps[subtree]; // Else create a unique name, and add it to the hash table @@ -3919,8 +3921,9 @@ void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count MatchRule* clone = new MatchRule(_AD, this); // Swap operands of commutative operation ((MatchNode*)clone)->swap_commutative_op(true, count); - char* buf = (char*) AdlAllocateHeap(strlen(instr_ident) + 4); - sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++); + const size_t buf_size = strlen(instr_ident) + 4; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "%s_%d", instr_ident, match_rules_cnt++); clone->_result = buf; clone->_next = this->_next; @@ -4223,7 +4226,7 @@ bool MatchRule::is_vector() const { "VectorTest", "VectorLoadMask", "VectorStoreMask", "VectorBlend", "VectorInsert", "VectorRearrange","VectorLoadShuffle", "VectorLoadConst", "VectorCastB2X", "VectorCastS2X", "VectorCastI2X", - "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", + "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorCastF2HF", "VectorCastHF2F", "VectorUCastB2X", "VectorUCastS2X", "VectorUCastI2X", "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", "FmaVD","FmaVF","PopCountVI","PopCountVL","PopulateIndex","VectorLongToMask", diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp index 5016c540f11..dce3f2309f8 100644 --- a/src/hotspot/share/adlc/main.cpp +++ b/src/hotspot/share/adlc/main.cpp @@ -466,7 +466,7 @@ static char *base_plus_suffix(const char* base, const char *suffix) int len = (int)strlen(base) + (int)strlen(suffix) + 1; char* fname = new char[len]; - sprintf(fname,"%s%s",base,suffix); + snprintf_checked(fname,len,"%s%s",base,suffix); return fname; } diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 264012b8f15..93b32b73cbd 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -26,6 +26,8 @@ #include "adlc.hpp" +#define remaining_buflen(buffer, position) (sizeof(buffer) - (position - buffer)) + // Utilities to characterize effect statements static bool is_def(int usedef) { switch(usedef) { @@ -35,6 +37,16 @@ static bool is_def(int usedef) { return false; } +int snprintf_checked(char* buf, size_t len, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + int result = vsnprintf(buf, len, fmt, args); + va_end(args); + assert(result >= 0, "snprintf error"); + assert(static_cast(result) < len, "snprintf truncated"); + return result; +} + // Define an array containing the machine register names, strings. static void defineRegNames(FILE *fp, RegisterForm *registers) { if (registers) { @@ -197,7 +209,8 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi return -1; } - char *operand_stages = new char [templen]; + const size_t operand_stages_size = templen; + char *operand_stages = new char [operand_stages_size]; operand_stages[0] = 0; int i = 0; templen = 0; @@ -211,7 +224,7 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi while ( (paramname = pipeclass->_parameters.iter()) != NULL ) { const PipeClassOperandForm *tmppipeopnd = (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; - templen += sprintf(&operand_stages[templen], " stage_%s%c\n", + templen += snprintf_checked(&operand_stages[templen], operand_stages_size - templen, " stage_%s%c\n", tmppipeopnd ? tmppipeopnd->_stage : "undefined", (++i < paramcount ? ',' : ' ') ); } @@ -278,6 +291,7 @@ static int pipeline_res_stages_initializer( int templen = 1 + commentlen + pipeline->_rescount * (max_stage + 14); // Allocate space for the resource list + const size_t resource_stages_size = templen; char * resource_stages = new char [templen]; templen = 0; @@ -285,7 +299,7 @@ static int pipeline_res_stages_initializer( const char * const resname = res_stages[i] == 0 ? "undefined" : pipeline->_stages.name(res_stages[i]-1); - templen += sprintf(&resource_stages[templen], " stage_%s%-*s // %s\n", + templen += snprintf_checked(&resource_stages[templen], resource_stages_size - templen, " stage_%s%-*s // %s\n", resname, max_stage - (int)strlen(resname) + 1, (i < pipeline->_rescount-1) ? "," : "", pipeline->_reslist.name(i)); @@ -344,7 +358,7 @@ static int pipeline_res_cycles_initializer( for (i = 0; i < pipeline->_rescount; i++) { if (max_cycles < res_cycles[i]) max_cycles = res_cycles[i]; - templen = sprintf(temp, "%d", res_cycles[i]); + templen = snprintf_checked(temp, sizeof(temp), "%d", res_cycles[i]); if (cyclelen < templen) cyclelen = templen; commentlen += (int)strlen(pipeline->_reslist.name(i)); @@ -353,12 +367,13 @@ static int pipeline_res_cycles_initializer( templen = 1 + commentlen + (cyclelen + 8) * pipeline->_rescount; // Allocate space for the resource list - char * resource_cycles = new char [templen]; + const size_t resource_cycles_size = templen; + char * resource_cycles = new char [resource_cycles_size]; templen = 0; for (i = 0; i < pipeline->_rescount; i++) { - templen += sprintf(&resource_cycles[templen], " %*d%c // %s\n", + templen += snprintf_checked(&resource_cycles[templen], resource_cycles_size - templen, " %*d%c // %s\n", cyclelen, res_cycles[i], (i < pipeline->_rescount-1) ? ',' : ' ', pipeline->_reslist.name(i)); } @@ -431,7 +446,8 @@ static int pipeline_res_mask_initializer( (cyclemasksize * 12) + masklen + (cycledigit * 2) + 30) * element_count; // Allocate space for the resource list - char * resource_mask = new char [templen]; + const size_t resource_mask_size = templen; + char * resource_mask = new char [resource_mask_size]; char * last_comma = NULL; templen = 0; @@ -456,7 +472,7 @@ static int pipeline_res_mask_initializer( } int formatlen = - sprintf(&resource_mask[templen], " %s(0x%0*x, %*d, %*d, %s %s(", + snprintf_checked(&resource_mask[templen], resource_mask_size - templen, " %s(0x%0*x, %*d, %*d, %s %s(", pipeline_use_element, masklen, used_mask, cycledigit, lb, cycledigit, ub, @@ -496,7 +512,7 @@ static int pipeline_res_mask_initializer( for (j = cyclemasksize-1; j >= 0; j--) { formatlen = - sprintf(&resource_mask[templen], "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); + snprintf_checked(&resource_mask[templen], resource_mask_size - templen, "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); templen += formatlen; } @@ -527,9 +543,8 @@ static int pipeline_res_mask_initializer( // "0x012345678, 0x012345678, 4294967295" char* args = new char [36 + 1]; - int printed = sprintf(args, "0x%x, 0x%x, %u", - resources_used, resources_used_exclusively, element_count); - assert(printed <= 36, "overflow"); + snprintf_checked(args, 36 + 1, "0x%x, 0x%x, %u", + resources_used, resources_used_exclusively, element_count); pipeline_res_args.addName(args); } @@ -1066,9 +1081,9 @@ static void build_instruction_index_mapping( FILE *fp, FormDict &globals, PeepMa InstructForm *inst = globals[inst_name]->is_instruction(); if( inst != NULL ) { char inst_prefix[] = "instXXXX_"; - sprintf(inst_prefix, "inst%d_", inst_position); + snprintf_checked(inst_prefix, sizeof(inst_prefix), "inst%d_", inst_position); char receiver[] = "instXXXX->"; - sprintf(receiver, "inst%d->", inst_position); + snprintf_checked(receiver, sizeof(receiver), "inst%d->", inst_position); inst->index_temps( fp, globals, inst_prefix, receiver ); } } @@ -1162,7 +1177,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch char left_reg_index[] = ",inst4294967295_idx4294967295"; if( left_op_index != 0 ) { // Must have index into operands - sprintf(left_reg_index,",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index); + snprintf_checked(left_reg_index, sizeof(left_reg_index), ",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index); } else { strcpy(left_reg_index, ""); } @@ -1174,7 +1189,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch char right_reg_index[] = ",inst4294967295_idx4294967295"; if( right_op_index != 0 ) { // Must have index into operands - sprintf(right_reg_index,",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index); + snprintf_checked(right_reg_index, sizeof(right_reg_index), ",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index); } else { strcpy(right_reg_index, ""); } @@ -2563,19 +2578,19 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { const char* arg_name = ins_encode->rep_var_name(inst, param_no); int idx = inst.operand_position_format(arg_name); if (strcmp(arg_name, "constanttablebase") == 0) { - ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", + ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", name, type, arg_name); - nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); + nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name); // There is no operand for the constanttablebase. } else if (inst.is_noninput_operand(idx)) { globalAD->syntax_err(inst._linenum, "In %s: you can not pass the non-input %s to a postalloc expand encoding.\n", inst._ident, arg_name); } else { - ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", + ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", name, idx, type, arg_name); - nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); - ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); + nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name); + ob += snprintf_checked(ob, remaining_buflen(opbuf, ob), " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); } param_no++; } diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 485fa53face..f9ffd169e38 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -348,8 +348,8 @@ void CodeSection::relocate(address at, RelocationHolder const& spec, int format) // each carrying the largest possible offset, to advance the locs_point. while (offset >= relocInfo::offset_limit()) { assert(end < locs_limit(), "adjust previous paragraph of code"); - *end++ = filler_relocInfo(); - offset -= filler_relocInfo().addr_offset(); + *end++ = relocInfo::filler_info(); + offset -= relocInfo::filler_info().addr_offset(); } // If it's a simple reloc with no data, we'll just write (rtype | offset). @@ -634,7 +634,7 @@ csize_t CodeBuffer::copy_relocations_to(address buf, csize_t buf_limit, bool onl code_point_so_far < new_code_point; code_point_so_far += jump) { jump = new_code_point - code_point_so_far; - relocInfo filler = filler_relocInfo(); + relocInfo filler = relocInfo::filler_info(); if (jump >= filler.addr_offset()) { jump = filler.addr_offset(); } else { // else shrink the filler to fit diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index ef741e82943..819ee6adeb9 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -154,7 +154,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_getModifiers: case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: - case vmIntrinsics::_extentLocalCache: + case vmIntrinsics::_scopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsqrt_strict: diff --git a/src/hotspot/share/c1/c1_Defs.hpp b/src/hotspot/share/c1/c1_Defs.hpp index 183509e3b26..4d3763e07ba 100644 --- a/src/hotspot/share/c1/c1_Defs.hpp +++ b/src/hotspot/share/c1/c1_Defs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -56,4 +56,9 @@ enum { float_saved_as_double = pd_float_saved_as_double }; +// true if LIR requires src1 and dst to match in binary LIR ops +enum { + two_operand_lir_form = pd_two_operand_lir_form +}; + #endif // SHARE_C1_C1_DEFS_HPP diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index d07274f785f..5b903192c9e 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -194,7 +194,7 @@ void LIR_Op2::verify() const { "can't produce oops from arith"); } - if (TwoOperandLIRForm) { + if (two_operand_lir_form) { #ifdef ASSERT bool threeOperandForm = false; diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index f6f0a6ac28b..a40c7b19b6d 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -491,7 +491,7 @@ void LIRGenerator::arithmetic_op(Bytecodes::Code code, LIR_Opr result, LIR_Opr l LIR_Opr left_op = left; LIR_Opr right_op = right; - if (TwoOperandLIRForm && left_op != result_op) { + if (two_operand_lir_form && left_op != result_op) { assert(right_op != result_op, "malformed"); __ move(left_op, result_op); left_op = result_op; @@ -563,7 +563,7 @@ void LIRGenerator::arithmetic_op_fpu(Bytecodes::Code code, LIR_Opr result, LIR_O void LIRGenerator::shift_op(Bytecodes::Code code, LIR_Opr result_op, LIR_Opr value, LIR_Opr count, LIR_Opr tmp) { - if (TwoOperandLIRForm && value != result_op + if (two_operand_lir_form && value != result_op // Only 32bit right shifts require two operand form on S390. S390_ONLY(&& (code == Bytecodes::_ishr || code == Bytecodes::_iushr))) { assert(count != result_op, "malformed"); @@ -585,7 +585,7 @@ void LIRGenerator::shift_op(Bytecodes::Code code, LIR_Opr result_op, LIR_Opr val void LIRGenerator::logic_op (Bytecodes::Code code, LIR_Opr result_op, LIR_Opr left_op, LIR_Opr right_op) { - if (TwoOperandLIRForm && left_op != result_op) { + if (two_operand_lir_form && left_op != result_op) { assert(right_op != result_op, "malformed"); __ move(left_op, result_op); left_op = result_op; @@ -1428,8 +1428,8 @@ void LIRGenerator::do_getObjectSize(Intrinsic* x) { __ branch_destination(L_done->label()); } -void LIRGenerator::do_extentLocalCache(Intrinsic* x) { - do_JavaThreadField(x, JavaThread::extentLocalCache_offset()); +void LIRGenerator::do_scopedValueCache(Intrinsic* x) { + do_JavaThreadField(x, JavaThread::scopedValueCache_offset()); } // Example: Thread.currentCarrierThread() @@ -2948,7 +2948,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_getObjectSize: do_getObjectSize(x); break; case vmIntrinsics::_currentCarrierThread: do_currentCarrierThread(x); break; case vmIntrinsics::_currentThread: do_vthread(x); break; - case vmIntrinsics::_extentLocalCache: do_extentLocalCache(x); break; + case vmIntrinsics::_scopedValueCache: do_scopedValueCache(x); break; case vmIntrinsics::_dlog: // fall through case vmIntrinsics::_dlog10: // fall through @@ -3547,7 +3547,7 @@ void LIRGenerator::do_MemBar(MemBar* x) { LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) { LIR_Opr value_fixed = rlock_byte(T_BYTE); - if (TwoOperandLIRForm) { + if (two_operand_lir_form) { __ move(value, value_fixed); __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed); } else { diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp index aedba60e973..7f4b25e89f1 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.hpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp @@ -257,7 +257,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_getClass(Intrinsic* x); void do_getObjectSize(Intrinsic* x); void do_currentCarrierThread(Intrinsic* x); - void do_extentLocalCache(Intrinsic* x); + void do_scopedValueCache(Intrinsic* x); void do_vthread(Intrinsic* x); void do_JavaThreadField(Intrinsic* x, ByteSize offset); void do_FmaIntrinsic(Intrinsic* x); diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 9e02d9f323d..4efb95fff80 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -688,7 +688,7 @@ JRT_ENTRY(void, Runtime1::throw_range_check_exception(JavaThread* current, int i const int len = 35; assert(len < strlen("Index %d out of bounds for length %d"), "Must allocate more space for message."); char message[2 * jintAsStringSize + len]; - sprintf(message, "Index %d out of bounds for length %d", index, a->length()); + os::snprintf_checked(message, sizeof(message), "Index %d out of bounds for length %d", index, a->length()); SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); JRT_END @@ -700,7 +700,7 @@ JRT_ENTRY(void, Runtime1::throw_index_exception(JavaThread* current, int index)) } #endif char message[16]; - sprintf(message, "%d", index); + os::snprintf_checked(message, sizeof(message), "%d", index); SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IndexOutOfBoundsException(), message); JRT_END diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index 7f425680b47..1c22cf16cfe 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -203,9 +203,6 @@ develop_pd(bool, CSEArrayLength, \ "Create separate nodes for length in array accesses") \ \ - develop_pd(bool, TwoOperandLIRForm, \ - "true if LIR requires src1 and dst to match in binary LIR ops") \ - \ develop(intx, TraceLinearScanLevel, 0, \ "Debug levels for the linear scan allocator") \ range(0, 4) \ diff --git a/src/hotspot/share/cds/archiveHeapLoader.cpp b/src/hotspot/share/cds/archiveHeapLoader.cpp index aa84ce15407..ce5eb2b6e75 100644 --- a/src/hotspot/share/cds/archiveHeapLoader.cpp +++ b/src/hotspot/share/cds/archiveHeapLoader.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "cds/archiveHeapLoader.inline.hpp" -#include "cds/filemap.hpp" #include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/classLoaderDataShared.hpp" @@ -114,12 +113,35 @@ class PatchCompressedEmbeddedPointers: public BitMapClosure { narrowOop* p = _start + offset; narrowOop v = *p; assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time"); - oop o = ArchiveHeapLoader::decode_from_archive(v); + oop o = ArchiveHeapLoader::decode_from_mapped_archive(v); RawAccess::oop_store(p, o); return true; } }; +class PatchCompressedEmbeddedPointersQuick: public BitMapClosure { + narrowOop* _start; + uint32_t _delta; + + public: + PatchCompressedEmbeddedPointersQuick(narrowOop* start, uint32_t delta) : _start(start), _delta(delta) {} + + bool do_bit(size_t offset) { + narrowOop* p = _start + offset; + narrowOop v = *p; + assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time"); + narrowOop new_v = CompressedOops::narrow_oop_cast(CompressedOops::narrow_oop_value(v) + _delta); + assert(!CompressedOops::is_null(new_v), "should never relocate to narrowOop(0)"); +#ifdef ASSERT + oop o1 = ArchiveHeapLoader::decode_from_mapped_archive(v); + oop o2 = CompressedOops::decode_not_null(new_v); + assert(o1 == o2, "quick delta must work"); +#endif + RawAccess::oop_store(p, new_v); + return true; + } +}; + class PatchUncompressedEmbeddedPointers: public BitMapClosure { oop* _start; @@ -136,9 +158,38 @@ class PatchUncompressedEmbeddedPointers: public BitMapClosure { } }; +void ArchiveHeapLoader::patch_compressed_embedded_pointers(BitMapView bm, + FileMapInfo* info, + FileMapRegion* map_region, + MemRegion region) { + narrowOop dt_encoded_bottom = info->encoded_heap_region_dumptime_address(map_region); + narrowOop rt_encoded_bottom = CompressedOops::encode_not_null(cast_to_oop(region.start())); + log_info(cds)("patching heap embedded pointers: narrowOop 0x%8x -> 0x%8x", + (uint)dt_encoded_bottom, (uint)rt_encoded_bottom); + + // Optimization: if dumptime shift is the same as runtime shift, we can perform a + // quick conversion from "dumptime narrowOop" -> "runtime narrowOop". + if (_narrow_oop_shift == CompressedOops::shift()) { + uint32_t quick_delta = (uint32_t)rt_encoded_bottom - (uint32_t)dt_encoded_bottom; + log_info(cds)("CDS heap data relocation quick delta = 0x%x", quick_delta); + if (quick_delta == 0) { + log_info(cds)("CDS heap data relocation unnecessary, quick_delta = 0"); + } else { + PatchCompressedEmbeddedPointersQuick patcher((narrowOop*)region.start(), quick_delta); + bm.iterate(&patcher); + } + } else { + log_info(cds)("CDS heap data quick relocation not possible"); + PatchCompressedEmbeddedPointers patcher((narrowOop*)region.start()); + bm.iterate(&patcher); + } +} + // Patch all the non-null pointers that are embedded in the archived heap objects // in this (mapped) region -void ArchiveHeapLoader::patch_embedded_pointers(MemRegion region, address oopmap, +void ArchiveHeapLoader::patch_embedded_pointers(FileMapInfo* info, + FileMapRegion* map_region, + MemRegion region, address oopmap, size_t oopmap_size_in_bits) { BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits); @@ -149,8 +200,7 @@ void ArchiveHeapLoader::patch_embedded_pointers(MemRegion region, address oopmap #endif if (UseCompressedOops) { - PatchCompressedEmbeddedPointers patcher((narrowOop*)region.start()); - bm.iterate(&patcher); + patch_compressed_embedded_pointers(bm, info, map_region, region); } else { PatchUncompressedEmbeddedPointers patcher((oop*)region.start()); bm.iterate(&patcher); diff --git a/src/hotspot/share/cds/archiveHeapLoader.hpp b/src/hotspot/share/cds/archiveHeapLoader.hpp index 97e0edf6314..754893cb4fa 100644 --- a/src/hotspot/share/cds/archiveHeapLoader.hpp +++ b/src/hotspot/share/cds/archiveHeapLoader.hpp @@ -25,12 +25,14 @@ #ifndef SHARE_CDS_ARCHIVEHEAPLOADER_HPP #define SHARE_CDS_ARCHIVEHEAPLOADER_HPP +#include "cds/filemap.hpp" #include "gc/shared/gc_globals.hpp" #include "memory/allocation.hpp" #include "memory/allStatic.hpp" #include "memory/memRegion.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/globals.hpp" +#include "utilities/bitMap.hpp" #include "utilities/macros.hpp" class FileMapInfo; @@ -103,8 +105,18 @@ class ArchiveHeapLoader : AllStatic { // function instead. inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static void patch_embedded_pointers(MemRegion region, address oopmap, - size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN; + // More efficient version, but works only when ArchiveHeap is mapped. + inline static oop decode_from_mapped_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + + static void patch_compressed_embedded_pointers(BitMapView bm, + FileMapInfo* info, + FileMapRegion* map_region, + MemRegion region) NOT_CDS_JAVA_HEAP_RETURN; + + static void patch_embedded_pointers(FileMapInfo* info, + FileMapRegion* map_region, + MemRegion region, address oopmap, + size_t oopmap_size_in_bits) NOT_CDS_JAVA_HEAP_RETURN; static void fixup_regions() NOT_CDS_JAVA_HEAP_RETURN; @@ -159,6 +171,9 @@ class ArchiveHeapLoader : AllStatic { return (_loaded_heap_bottom <= o && o < _loaded_heap_top); } + template + inline static oop decode_from_archive_impl(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + public: static bool load_heap_regions(FileMapInfo* mapinfo); diff --git a/src/hotspot/share/cds/archiveHeapLoader.inline.hpp b/src/hotspot/share/cds/archiveHeapLoader.inline.hpp index 34ac6e15a1a..6f344ddf526 100644 --- a/src/hotspot/share/cds/archiveHeapLoader.inline.hpp +++ b/src/hotspot/share/cds/archiveHeapLoader.inline.hpp @@ -32,11 +32,14 @@ #if INCLUDE_CDS_JAVA_HEAP -inline oop ArchiveHeapLoader::decode_from_archive(narrowOop v) { +template +inline oop ArchiveHeapLoader::decode_from_archive_impl(narrowOop v) { assert(!CompressedOops::is_null(v), "narrow oop value can never be zero"); assert(_narrow_oop_base_initialized, "relocation information must have been initialized"); uintptr_t p = ((uintptr_t)_narrow_oop_base) + ((uintptr_t)v << _narrow_oop_shift); - if (p >= _dumptime_base_0) { + if (IS_MAPPED) { + assert(_dumptime_base_0 == UINTPTR_MAX, "must be"); + } else if (p >= _dumptime_base_0) { assert(p < _dumptime_top, "must be"); if (p >= _dumptime_base_3) { p += _runtime_offset_3; @@ -54,6 +57,14 @@ inline oop ArchiveHeapLoader::decode_from_archive(narrowOop v) { return result; } +inline oop ArchiveHeapLoader::decode_from_archive(narrowOop v) { + return decode_from_archive_impl(v); +} + +inline oop ArchiveHeapLoader::decode_from_mapped_archive(narrowOop v) { + return decode_from_archive_impl(v); +} + #endif #endif // SHARE_CDS_ARCHIVEHEAPLOADER_INLINE_HPP diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index 710c87069b0..c02caced364 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -236,7 +236,7 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& ls.print("Value: "); orig_obj->print_on(&ls); ls.print_cr("--- trace begin ---"); - trace_to_root(orig_obj, NULL, &value); + trace_to_root(&ls, orig_obj, NULL, &value); ls.print_cr("--- trace end ---"); ls.cr(); _problems ++; @@ -248,54 +248,62 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& class CDSHeapVerifier::TraceFields : public FieldClosure { oop _orig_obj; oop _orig_field; - LogStream* _ls; + outputStream* _st; public: - TraceFields(oop orig_obj, oop orig_field, LogStream* ls) - : _orig_obj(orig_obj), _orig_field(orig_field), _ls(ls) {} + TraceFields(oop orig_obj, oop orig_field, outputStream* st) + : _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {} void do_field(fieldDescriptor* fd) { if (fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY) { oop obj_field = _orig_obj->obj_field(fd->offset()); if (obj_field == _orig_field) { - _ls->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset()); + _st->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset()); } } } }; -// Hint: to exercise this function, uncomment out one of the ADD_EXCL lines above. -int CDSHeapVerifier::trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p) { +// Call this function (from gdb, etc) if you want to know why an object is archived. +void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) { + HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(orig_obj); + if (info != NULL) { + trace_to_root(st, orig_obj, NULL, info); + } else { + st->print_cr("Not an archived object??"); + } +} + +int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) { int level = 0; - LogStream ls(Log(cds, heap)::warning()); - if (p->_referrer != NULL) { - HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(p->_referrer); + if (info->_referrer != NULL) { + HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->_referrer); assert(ref != NULL, "sanity"); - level = trace_to_root(p->_referrer, orig_obj, ref) + 1; + level = trace_to_root(st, info->_referrer, orig_obj, ref) + 1; } else if (java_lang_String::is_instance(orig_obj)) { - ls.print_cr("[%2d] (shared string table)", level++); + st->print_cr("[%2d] (shared string table)", level++); } Klass* k = orig_obj->klass(); ResourceMark rm; - ls.print("[%2d] ", level); - orig_obj->print_address_on(&ls); - ls.print(" %s", k->internal_name()); + st->print("[%2d] ", level); + orig_obj->print_address_on(st); + st->print(" %s", k->internal_name()); if (orig_field != NULL) { if (k->is_instance_klass()) { - TraceFields clo(orig_obj, orig_field, &ls);; + TraceFields clo(orig_obj, orig_field, st); InstanceKlass::cast(k)->do_nonstatic_fields(&clo); } else { assert(orig_obj->is_objArray(), "must be"); objArrayOop array = (objArrayOop)orig_obj; for (int i = 0; i < array->length(); i++) { if (array->obj_at(i) == orig_field) { - ls.print(" @[%d]", i); + st->print(" @[%d]", i); break; } } } } - ls.cr(); + st->cr(); return level; } diff --git a/src/hotspot/share/cds/cdsHeapVerifier.hpp b/src/hotspot/share/cds/cdsHeapVerifier.hpp index 6bc8c7ddd87..947308e24e8 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.hpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.hpp @@ -69,7 +69,7 @@ class CDSHeapVerifier : public KlassClosure { } return NULL; } - int trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); + static int trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); CDSHeapVerifier(); ~CDSHeapVerifier(); @@ -83,6 +83,8 @@ class CDSHeapVerifier : public KlassClosure { inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value); static void verify() NOT_DEBUG_RETURN; + + static void trace_to_root(outputStream* st, oop orig_obj); }; #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/cdsProtectionDomain.cpp b/src/hotspot/share/cds/cdsProtectionDomain.cpp index 7f8c25d9ae5..6992fd0d5dc 100644 --- a/src/hotspot/share/cds/cdsProtectionDomain.cpp +++ b/src/hotspot/share/cds/cdsProtectionDomain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "cds/cdsProtectionDomain.hpp" #include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.hpp" #include "classfile/moduleEntry.hpp" @@ -125,7 +126,7 @@ PackageEntry* CDSProtectionDomain::get_package_entry_from_class(InstanceKlass* i } TempNewSymbol pkg_name = ClassLoader::package_from_class_name(ik->name()); if (pkg_name != NULL) { - pkg_entry = SystemDictionaryShared::class_loader_data(class_loader)->packages()->lookup_only(pkg_name); + pkg_entry = ClassLoaderData::class_loader_data(class_loader())->packages()->lookup_only(pkg_name); } else { pkg_entry = NULL; } @@ -292,7 +293,7 @@ void CDSProtectionDomain::atomic_set_array_index(OopHandle array, int index, oop // The important thing here is that all threads pick up the same result. // It doesn't matter which racing thread wins, as long as only one // result is used by all threads, and all future queries. - ((objArrayOop)array.resolve())->atomic_compare_exchange_oop(index, o, NULL); + ((objArrayOop)array.resolve())->replace_if_null(index, o); } oop CDSProtectionDomain::shared_protection_domain(int index) { diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index e08917aa30b..6c792c0fd2b 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -169,7 +169,7 @@ template static void get_header_version(char (&header_version) [N]) { strncpy(header_version, vm_version, JVM_IDENT_MAX-9); // Append the hash code as eight hex digits. - sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); + os::snprintf_checked(&header_version[JVM_IDENT_MAX-9], 9, "%08x", hash); header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. } @@ -880,11 +880,13 @@ unsigned int FileMapInfo::longest_common_app_classpath_prefix_len(int num_paths, if (rp_array->at(i)[pos] != '\0' && rp_array->at(i)[pos] == rp_array->at(0)[pos]) { continue; } - // search backward for the pos before the file separator char - while (pos > 0 && rp_array->at(0)[--pos] != *os::file_separator()); - // return the file separator char position - return pos + 1; + while (pos > 0) { + if (rp_array->at(0)[--pos] == *os::file_separator()) { + return pos + 1; + } + } + return 0; } } return 0; @@ -1022,8 +1024,12 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) { // java -Xshare:auto -cp /x/y/Foo.jar:/x/y/b/Bar.jar ... unsigned int dumptime_prefix_len = header()->common_app_classpath_prefix_size(); unsigned int runtime_prefix_len = longest_common_app_classpath_prefix_len(shared_app_paths_len, rp_array); - mismatch = check_paths(j, shared_app_paths_len, rp_array, - dumptime_prefix_len, runtime_prefix_len); + if (dumptime_prefix_len != 0 || runtime_prefix_len != 0) { + log_info(class, path)("LCP length for app classpath (dumptime: %u, runtime: %u)", + dumptime_prefix_len, runtime_prefix_len); + mismatch = check_paths(j, shared_app_paths_len, rp_array, + dumptime_prefix_len, runtime_prefix_len); + } if (mismatch) { return classpath_failure("[APP classpath mismatch, actual: -Djava.class.path=", appcp); } @@ -2060,6 +2066,20 @@ size_t FileMapInfo::read_bytes(void* buffer, size_t count) { return count; } +// Get the total size in bytes of a read only region +size_t FileMapInfo::readonly_total() { + size_t total = 0; + if (current_info() != nullptr) { + FileMapRegion* r = FileMapInfo::current_info()->region_at(MetaspaceShared::ro); + if (r->read_only()) total += r->used(); + } + if (dynamic_info() != nullptr) { + FileMapRegion* r = FileMapInfo::dynamic_info()->region_at(MetaspaceShared::ro); + if (r->read_only()) total += r->used(); + } + return total; +} + static MemRegion *closed_heap_regions = NULL; static MemRegion *open_heap_regions = NULL; static int num_closed_heap_regions = 0; @@ -2433,6 +2453,13 @@ void FileMapInfo::patch_heap_embedded_pointers() { MetaspaceShared::first_open_heap_region); } +narrowOop FileMapInfo::encoded_heap_region_dumptime_address(FileMapRegion* r) { + assert(UseSharedSpaces, "runtime only"); + assert(UseCompressedOops, "sanity"); + r->assert_is_heap_region(); + return CompressedOops::narrow_oop_cast(r->mapping_offset() >> narrow_oop_shift()); +} + void FileMapInfo::patch_heap_embedded_pointers(MemRegion* regions, int num_regions, int first_region_idx) { char* bitmap_base = map_bitmap_region(); @@ -2440,24 +2467,9 @@ void FileMapInfo::patch_heap_embedded_pointers(MemRegion* regions, int num_regio for (int i=0; imapping_offset() >> narrow_oop_shift()); - narrowOop rt_encoded_bottom = CompressedOops::encode_not_null(cast_to_oop(regions[i].start())); - log_info(cds)("patching heap embedded pointers for %s: narrowOop 0x%8x -> 0x%8x", - region_name(region_idx), (uint)dt_encoded_bottom, (uint)rt_encoded_bottom); - // TODO JDK-8269736: if we have the same narrow_oop_shift between dumptime and runtime, - // Each embedded pointer P can be updated by: - // P += (rt_encoded_bottom - dt_encoded_bottom) - // - // TODO: - // if (dt_encoded_bottom == rt_encoded_bottom && narrow_oop_shift() == CompressedOops::shift()) { - // //nothing to do - // return; - // } - } + ArchiveHeapLoader::patch_embedded_pointers( - regions[i], + this, r, regions[i], (address)(region_at(MetaspaceShared::bm)->mapped_base()) + r->oopmap_offset(), r->oopmap_size_in_bits()); } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index a67274d532a..541b8fd603a 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -460,6 +460,7 @@ class FileMapInfo : public CHeapObj { void write_bytes(const void* buffer, size_t count); void write_bytes_aligned(const void* buffer, size_t count); size_t read_bytes(void* buffer, size_t count); + static size_t readonly_total(); MapArchiveResult map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs); void unmap_regions(int regions[], int num_regions); void map_or_load_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; @@ -592,6 +593,7 @@ class FileMapInfo : public CHeapObj { address heap_region_dumptime_address(FileMapRegion* r) NOT_CDS_JAVA_HEAP_RETURN_(NULL); address heap_region_requested_address(FileMapRegion* r) NOT_CDS_JAVA_HEAP_RETURN_(NULL); address heap_region_mapped_address(FileMapRegion* r) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + narrowOop encoded_heap_region_dumptime_address(FileMapRegion* r); private: diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 6a37a50f127..0f5cee30939 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -30,9 +30,8 @@ #include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/classLoaderData.hpp" -#include "classfile/classLoaderDataShared.hpp" #include "classfile/javaClasses.inline.hpp" -#include "classfile/moduleEntry.hpp" +#include "classfile/modules.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" @@ -84,6 +83,11 @@ bool HeapShared::_disable_writing = false; DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL; GrowableArrayCHeap* HeapShared::_native_pointers = NULL; +size_t HeapShared::_alloc_count[HeapShared::ALLOC_STAT_SLOTS]; +size_t HeapShared::_alloc_size[HeapShared::ALLOC_STAT_SLOTS]; +size_t HeapShared::_total_obj_count; +size_t HeapShared::_total_obj_size; + #ifndef PRODUCT #define ARCHIVE_TEST_FIELD_NAME "archivedObjects" static Array* _archived_ArchiveHeapTestClass = NULL; @@ -301,6 +305,7 @@ oop HeapShared::archive_object(oop obj) { oop archived_oop = cast_to_oop(G1CollectedHeap::heap()->archive_mem_allocate(len)); if (archived_oop != NULL) { + count_allocation(len); Copy::aligned_disjoint_words(cast_from_oop(obj), cast_from_oop(archived_oop), len); // Reinitialize markword to remove age/marking/locking/etc. // @@ -548,7 +553,7 @@ void HeapShared::copy_open_objects(GrowableArray* open_regions) { archive_object_subgraphs(fmg_open_archive_subgraph_entry_fields, false /* is_closed_archive */, true /* is_full_module_graph */); - ClassLoaderDataShared::init_archived_oops(); + Modules::verify_archived_modules(); } copy_roots(); @@ -586,6 +591,7 @@ void HeapShared::copy_roots() { roots()->obj_at_put(i, _pending_roots->at(i)); } log_info(cds)("archived obj roots[%d] = " SIZE_FORMAT " words, klass = %p, obj = %p", length, size, k, mem); + count_allocation(roots()->size()); } // @@ -831,6 +837,9 @@ void HeapShared::write_subgraph_info_table() { _archived_ArchiveHeapTestClass = array; } #endif + if (log_is_enabled(Info, cds, heap)) { + print_stats(); + } } void HeapShared::serialize_root(SerializeClosure* soc) { @@ -1179,25 +1188,6 @@ void HeapShared::check_closed_region_object(InstanceKlass* k) { } } -void HeapShared::check_module_oop(oop orig_module_obj) { - assert(DumpSharedSpaces, "must be"); - assert(java_lang_Module::is_instance(orig_module_obj), "must be"); - ModuleEntry* orig_module_ent = java_lang_Module::module_entry_raw(orig_module_obj); - if (orig_module_ent == NULL) { - // These special Module objects are created in Java code. They are not - // defined via Modules::define_module(), so they don't have a ModuleEntry: - // java.lang.Module::ALL_UNNAMED_MODULE - // java.lang.Module::EVERYONE_MODULE - // jdk.internal.loader.ClassLoaders$BootClassLoader::unnamedModule - assert(java_lang_Module::name(orig_module_obj) == NULL, "must be unnamed"); - log_info(cds, heap)("Module oop with No ModuleEntry* @[" PTR_FORMAT "]", p2i(orig_module_obj)); - } else { - ClassLoaderData* loader_data = orig_module_ent->loader_data(); - assert(loader_data->is_builtin_class_loader_data(), "must be"); - } -} - - // (1) If orig_obj has not been archived yet, archive it. // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), // trace all objects that are reachable from it, and make sure these objects are archived. @@ -1266,9 +1256,10 @@ oop HeapShared::archive_reachable_objects_from(int level, } if (java_lang_Module::is_instance(orig_obj)) { - check_module_oop(orig_obj); + if (Modules::check_module_oop(orig_obj)) { + Modules::update_oops_in_archived_module(orig_obj, append_root(archived_obj)); + } java_lang_Module::set_module_entry(archived_obj, NULL); - java_lang_Module::set_loader(archived_obj, NULL); } else if (java_lang_ClassLoader::is_instance(orig_obj)) { // class_data will be restored explicitly at run time. guarantee(orig_obj == SystemDictionary::java_platform_loader() || @@ -1858,4 +1849,49 @@ ResourceBitMap HeapShared::calculate_ptrmap(MemRegion region) { } } +void HeapShared::count_allocation(size_t size) { + _total_obj_count ++; + _total_obj_size += size; + for (int i = 0; i < ALLOC_STAT_SLOTS; i++) { + if (size <= (size_t(1) << i)) { + _alloc_count[i] ++; + _alloc_size[i] += size; + return; + } + } +} + +static double avg_size(size_t size, size_t count) { + double avg = 0; + if (count > 0) { + avg = double(size * HeapWordSize) / double(count); + } + return avg; +} + +void HeapShared::print_stats() { + size_t huge_count = _total_obj_count; + size_t huge_size = _total_obj_size; + + for (int i = 0; i < ALLOC_STAT_SLOTS; i++) { + size_t byte_size_limit = (size_t(1) << i) * HeapWordSize; + size_t count = _alloc_count[i]; + size_t size = _alloc_size[i]; + log_info(cds, heap)(SIZE_FORMAT_W(8) " objects are <= " SIZE_FORMAT_W(-6) + " bytes (total " SIZE_FORMAT_W(8) " bytes, avg %8.1f bytes)", + count, byte_size_limit, size * HeapWordSize, avg_size(size, count)); + huge_count -= count; + huge_size -= size; + } + + log_info(cds, heap)(SIZE_FORMAT_W(8) " huge objects (total " SIZE_FORMAT_W(8) " bytes" + ", avg %8.1f bytes)", + huge_count, huge_size * HeapWordSize, + avg_size(huge_size, huge_count)); + log_info(cds, heap)(SIZE_FORMAT_W(8) " total objects (total " SIZE_FORMAT_W(8) " bytes" + ", avg %8.1f bytes)", + _total_obj_count, _total_obj_size * HeapWordSize, + avg_size(_total_obj_size, _total_obj_count)); +} + #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 9990ab825b3..c77009e5107 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -162,6 +162,15 @@ class HeapShared: AllStatic { static DumpedInternedStrings *_dumped_interned_strings; static GrowableArrayCHeap* _native_pointers; + // statistics + constexpr static int ALLOC_STAT_SLOTS = 16; + static size_t _alloc_count[ALLOC_STAT_SLOTS]; + static size_t _alloc_size[ALLOC_STAT_SLOTS]; + static size_t _total_obj_count; + static size_t _total_obj_size; // in HeapWords + + static void count_allocation(size_t size); + static void print_stats(); public: static unsigned oop_hash(oop const& p); static unsigned string_oop_hash(oop const& string) { @@ -292,7 +301,6 @@ class HeapShared: AllStatic { static bool has_been_seen_during_subgraph_recording(oop obj); static void set_has_been_seen_during_subgraph_recording(oop obj); - static void check_module_oop(oop orig_module_obj); static void copy_roots(); static void resolve_classes_for_subgraphs(JavaThread* current, ArchivableStaticFieldInfo fields[]); diff --git a/src/hotspot/share/ci/ciArrayKlass.cpp b/src/hotspot/share/ci/ciArrayKlass.cpp index e4d66f247a4..c9cf6cf85e3 100644 --- a/src/hotspot/share/ci/ciArrayKlass.cpp +++ b/src/hotspot/share/ci/ciArrayKlass.cpp @@ -26,7 +26,8 @@ #include "ci/ciArrayKlass.hpp" #include "ci/ciObjArrayKlass.hpp" #include "ci/ciTypeArrayKlass.hpp" -#include "ci/ciUtilities.hpp" +#include "ci/ciUtilities.inline.hpp" +#include "memory/universe.hpp" // ciArrayKlass // @@ -103,3 +104,4 @@ ciArrayKlass* ciArrayKlass::make(ciType* element_type) { return ciObjArrayKlass::make(element_type->as_klass()); } } + diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 814b6049710..b1884563cc9 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -692,7 +692,7 @@ ciConstant ciEnv::unbox_primitive_value(ciObject* cibox, BasicType expected_bt) // ciConstant ciEnv::get_resolved_constant(const constantPoolHandle& cpool, int obj_index) { assert(obj_index >= 0, ""); - oop obj = cpool->resolved_references()->obj_at(obj_index); + oop obj = cpool->resolved_reference_at(obj_index); if (obj == NULL) { // Unresolved constant. It is resolved when the corresponding slot contains a non-null reference. // Null constant is represented as a sentinel (non-null) value. @@ -1226,7 +1226,7 @@ int ciEnv::comp_level() { // ------------------------------------------------------------------ // ciEnv::compile_id -uint ciEnv::compile_id() { +int ciEnv::compile_id() { if (task() == NULL) return 0; return task()->compile_id(); } diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index 48947f99b23..21b442b6e05 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -366,7 +366,7 @@ class ciEnv : StackObj { // Handy forwards to the task: int comp_level(); // task()->comp_level() - uint compile_id(); // task()->compile_id() + int compile_id(); // task()->compile_id() // Register the result of a compilation. void register_method(ciMethod* target, diff --git a/src/hotspot/share/ci/ciField.cpp b/src/hotspot/share/ci/ciField.cpp index 485db1b2748..24bf59dcb91 100644 --- a/src/hotspot/share/ci/ciField.cpp +++ b/src/hotspot/share/ci/ciField.cpp @@ -225,7 +225,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) { // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") || holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") || - holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("java/lang/foreign") || + holder->is_in_package("jdk/internal/foreign/layout") || holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("jdk/internal/vm/vector") || holder->is_in_package("jdk/incubator/vector") || holder->is_in_package("java/lang")) return true; diff --git a/src/hotspot/share/ci/ciInstanceKlass.cpp b/src/hotspot/share/ci/ciInstanceKlass.cpp index 584e7d0b1ef..b9aa07a0b0b 100644 --- a/src/hotspot/share/ci/ciInstanceKlass.cpp +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp @@ -69,6 +69,7 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) : _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily + _transitive_interfaces = NULL; // Ensure that the metadata wrapped by the ciMetadata is kept alive by GC. // This is primarily useful for metadata which is considered as weak roots @@ -729,6 +730,32 @@ void ciInstanceKlass::dump_replay_instanceKlass(outputStream* out, InstanceKlass } } +GrowableArray* ciInstanceKlass::transitive_interfaces() const{ + if (_transitive_interfaces == NULL) { + const_cast(this)->compute_transitive_interfaces(); + } + return _transitive_interfaces; +} + +void ciInstanceKlass::compute_transitive_interfaces() { + GUARDED_VM_ENTRY( + InstanceKlass* ik = get_instanceKlass(); + Array* interfaces = ik->transitive_interfaces(); + int orig_length = interfaces->length(); + Arena* arena = CURRENT_ENV->arena(); + int transitive_interfaces_len = orig_length + (is_interface() ? 1 : 0); + GrowableArray* transitive_interfaces = new(arena)GrowableArray(arena, transitive_interfaces_len, + 0, NULL); + for (int i = 0; i < orig_length; i++) { + transitive_interfaces->append(CURRENT_ENV->get_instance_klass(interfaces->at(i))); + } + if (is_interface()) { + transitive_interfaces->append(this); + } + _transitive_interfaces = transitive_interfaces; + ); +} + void ciInstanceKlass::dump_replay_data(outputStream* out) { ResourceMark rm; diff --git a/src/hotspot/share/ci/ciInstanceKlass.hpp b/src/hotspot/share/ci/ciInstanceKlass.hpp index 81f3be93bc6..c970232778a 100644 --- a/src/hotspot/share/ci/ciInstanceKlass.hpp +++ b/src/hotspot/share/ci/ciInstanceKlass.hpp @@ -76,9 +76,11 @@ class ciInstanceKlass : public ciKlass { // A ciInstanceKlass that's not itself: one implementor. // Itself: more than one implementor. ciInstanceKlass* _implementor; + GrowableArray* _transitive_interfaces; void compute_injected_fields(); bool compute_injected_fields_helper(); + void compute_transitive_interfaces(); protected: ciInstanceKlass(Klass* k); @@ -292,6 +294,7 @@ class ciInstanceKlass : public ciKlass { bool has_trusted_loader() const { return _has_trusted_loader; } + GrowableArray* transitive_interfaces() const; // Replay support diff --git a/src/hotspot/share/ci/ciMethodType.cpp b/src/hotspot/share/ci/ciMethodType.cpp index 221982f91e0..f9cd22001a3 100644 --- a/src/hotspot/share/ci/ciMethodType.cpp +++ b/src/hotspot/share/ci/ciMethodType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -52,10 +52,3 @@ int ciMethodType::ptype_count() const { int ciMethodType::ptype_slot_count() const { GUARDED_VM_ENTRY(return java_lang_invoke_MethodType::ptype_slot_count(get_oop());) } - -ciType* ciMethodType::ptype_at(int index) const { - GUARDED_VM_ENTRY( - oop ptype = java_lang_invoke_MethodType::ptype(get_oop(), index); - return class_to_citype(ptype); - ) -} diff --git a/src/hotspot/share/ci/ciMethodType.hpp b/src/hotspot/share/ci/ciMethodType.hpp index 1cdf77893af..b626fa9c447 100644 --- a/src/hotspot/share/ci/ciMethodType.hpp +++ b/src/hotspot/share/ci/ciMethodType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -43,9 +43,7 @@ class ciMethodType : public ciInstance { ciType* rtype() const; int ptype_count() const; - int ptype_slot_count() const ; - - ciType* ptype_at(int index) const; + int ptype_slot_count() const; }; #endif // SHARE_CI_CIMETHODTYPE_HPP diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp index f1c2252cbff..d93cd4e4f56 100644 --- a/src/hotspot/share/ci/ciObjectFactory.cpp +++ b/src/hotspot/share/ci/ciObjectFactory.cpp @@ -167,6 +167,7 @@ void ciObjectFactory::init_shared_objects() { assert (obj->is_metadata(), "what else would it be?"); if (obj->is_loaded() && obj->is_instance_klass()) { obj->as_instance_klass()->compute_nonstatic_fields(); + obj->as_instance_klass()->transitive_interfaces(); } } } diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index b8b6eab1d03..e2a0ab7025c 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -142,6 +142,8 @@ #define JAVA_20_VERSION 64 +#define JAVA_21_VERSION 65 + void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { assert((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, @@ -2258,18 +2260,16 @@ void ClassFileParser::copy_method_annotations(ConstMethod* cm, // Method* to save footprint, so we only know the size of the resulting Method* when the // entire method attribute is parsed. // -// The promoted_flags parameter is used to pass relevant access_flags -// from the method back up to the containing klass. These flag values -// are added to klass's access_flags. +// The has_localvariable_table parameter is used to pass up the value to InstanceKlass. Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, bool is_interface, const ConstantPool* cp, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, TRAPS) { assert(cfs != NULL, "invariant"); assert(cp != NULL, "invariant"); - assert(promoted_flags != NULL, "invariant"); + assert(has_localvariable_table != NULL, "invariant"); ResourceMark rm(THREAD); // Parse fixed parts: @@ -2818,7 +2818,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, // Copy class file LVT's/LVTT's into the HotSpot internal LVT. if (total_lvt_length > 0) { - promoted_flags->set_has_localvariable_table(); + *has_localvariable_table = true; copy_localvariable_table(m->constMethod(), lvt_cnt, localvariable_table_length, @@ -2874,18 +2874,15 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, } -// The promoted_flags parameter is used to pass relevant access_flags -// from the methods back up to the containing klass. These flag values -// are added to klass's access_flags. // Side-effects: populates the _methods field in the parser void ClassFileParser::parse_methods(const ClassFileStream* const cfs, bool is_interface, - AccessFlags* promoted_flags, + bool* const has_localvariable_table, bool* has_final_method, bool* declares_nonstatic_concrete_methods, TRAPS) { assert(cfs != NULL, "invariant"); - assert(promoted_flags != NULL, "invariant"); + assert(has_localvariable_table != NULL, "invariant"); assert(has_final_method != NULL, "invariant"); assert(declares_nonstatic_concrete_methods != NULL, "invariant"); @@ -2905,7 +2902,7 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs, Method* method = parse_method(cfs, is_interface, _cp, - promoted_flags, + has_localvariable_table, CHECK); if (method->is_final()) { @@ -5331,6 +5328,10 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, assert(NULL == _record_components, "invariant"); assert(NULL == _permitted_subclasses, "invariant"); + if (_has_localvariable_table) { + ik->set_has_localvariable_table(true); + } + if (_has_final_method) { ik->set_has_final_method(); } @@ -5594,6 +5595,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _relax_verify(false), _has_nonstatic_concrete_methods(false), _declares_nonstatic_concrete_methods(false), + _has_localvariable_table(false), _has_final_method(false), _has_contended_fields(false), _has_finalizer(false), @@ -5899,19 +5901,15 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, assert(_fields != NULL, "invariant"); // Methods - AccessFlags promoted_flags; parse_methods(stream, _access_flags.is_interface(), - &promoted_flags, + &_has_localvariable_table, &_has_final_method, &_declares_nonstatic_concrete_methods, CHECK); assert(_methods != NULL, "invariant"); - // promote flags from parse_methods() to the klass' flags - _access_flags.add_promoted_flags(promoted_flags.as_int()); - if (_declares_nonstatic_concrete_methods) { _has_nonstatic_concrete_methods = true; } @@ -5998,13 +5996,17 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st CHECK); } Handle loader(THREAD, _loader_data->class_loader()); - _super_klass = (const InstanceKlass*) + if (loader.is_null() && super_class_name == vmSymbols::java_lang_Object()) { + _super_klass = vmClasses::Object_klass(); + } else { + _super_klass = (const InstanceKlass*) SystemDictionary::resolve_super_or_fail(_class_name, super_class_name, loader, _protection_domain, true, CHECK); + } } if (_super_klass != NULL) { diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 3fe2414e93a..d8bb95b8a7a 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -187,6 +187,7 @@ class ClassFileParser { bool _has_nonstatic_concrete_methods; bool _declares_nonstatic_concrete_methods; + bool _has_localvariable_table; bool _has_final_method; bool _has_contended_fields; @@ -267,12 +268,12 @@ class ClassFileParser { Method* parse_method(const ClassFileStream* const cfs, bool is_interface, const ConstantPool* cp, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, TRAPS); void parse_methods(const ClassFileStream* const cfs, bool is_interface, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, bool* const has_final_method, bool* const declares_nonstatic_concrete_methods, TRAPS); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 95153d07fe1..534412cb0f7 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -671,6 +671,18 @@ void ClassLoader::setup_bootstrap_search_path_impl(JavaThread* current, const ch } } +// Gets the exploded path for the named module. The memory for the path +// is allocated on the C heap if `c_heap` is true otherwise in the resource area. +static const char* get_exploded_module_path(const char* module_name, bool c_heap) { + const char *home = Arguments::get_java_home(); + const char file_sep = os::file_separator()[0]; + // 10 represents the length of "modules" + 2 file separators + \0 + size_t len = strlen(home) + strlen(module_name) + 10; + char *path = c_heap ? NEW_C_HEAP_ARRAY(char, len, mtModule) : NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name); + return path; +} + // During an exploded modules build, each module defined to the boot loader // will be added to the ClassLoader::_exploded_entries array. void ClassLoader::add_to_exploded_build_list(JavaThread* current, Symbol* module_sym) { @@ -680,12 +692,7 @@ void ClassLoader::add_to_exploded_build_list(JavaThread* current, Symbol* module // Find the module's symbol ResourceMark rm(current); const char *module_name = module_sym->as_C_string(); - const char *home = Arguments::get_java_home(); - const char file_sep = os::file_separator()[0]; - // 10 represents the length of "modules" + 2 file separators + \0 - size_t len = strlen(home) + strlen(module_name) + 10; - char *path = NEW_RESOURCE_ARRAY(char, len); - jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name); + const char *path = get_exploded_module_path(module_name, false); struct stat st; if (os::stat(path, &st) == 0) { @@ -1415,6 +1422,20 @@ char* ClassLoader::lookup_vm_options() { return options; } +bool ClassLoader::is_module_observable(const char* module_name) { + assert(JImageOpen != NULL, "jimage library should have been opened"); + if (JImage_file == NULL) { + struct stat st; + const char *path = get_exploded_module_path(module_name, true); + bool res = os::stat(path, &st) == 0; + FREE_C_HEAP_ARRAY(char, path); + return res; + } + jlong size; + const char *jimage_version = get_jimage_version_string(); + return (*JImageFindResource)(JImage_file, module_name, jimage_version, "module-info.class", &size) != 0; +} + #if INCLUDE_CDS void ClassLoader::initialize_shared_path(JavaThread* current) { if (Arguments::is_dumping_archive()) { diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 20e60b2e210..56aa0977739 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -374,6 +374,10 @@ class ClassLoader: AllStatic { static char* lookup_vm_options(); + // Determines if the named module is present in the + // modules jimage file or in the exploded modules directory. + static bool is_module_observable(const char* module_name); + static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name, const char* file_name, jlong &size); diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index adb7463b6bf..74cb71c3ebe 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -50,7 +50,7 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" #include "classfile/dictionary.hpp" -#include "classfile/javaClasses.hpp" +#include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" #include "classfile/symbolTable.hpp" @@ -67,9 +67,9 @@ #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/klass.inline.hpp" -#include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" +#include "oops/verifyOopClosure.hpp" #include "oops/weakHandle.inline.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" @@ -824,6 +824,7 @@ void ClassLoaderData::add_to_deallocate_list(Metadata* m) { _deallocate_list = new (mtClass) GrowableArray(100, mtClass); } _deallocate_list->append_if_missing(m); + ResourceMark rm; log_debug(class, loader, data)("deallocate added for %s", m->print_value_string()); ClassLoaderDataGraph::set_should_clean_deallocate_lists(); } @@ -1010,6 +1011,23 @@ void ClassLoaderData::print_on(outputStream* out) const { void ClassLoaderData::print() const { print_on(tty); } +class VerifyHandleOops : public OopClosure { + VerifyOopClosure vc; + public: + virtual void do_oop(oop* p) { + if (p != nullptr && *p != nullptr) { + oop o = *p; + if (!java_lang_Class::is_instance(o)) { + // is_instance will assert for an invalid oop. + // Walk the resolved_references array and other assorted oops in the + // CLD::_handles field. The mirror oops are followed by other heap roots. + o->oop_iterate(&vc); + } + } + } + virtual void do_oop(narrowOop* o) { ShouldNotReachHere(); } +}; + void ClassLoaderData::verify() { assert_locked_or_safepoint(_metaspace_lock); oop cl = class_loader(); @@ -1033,6 +1051,19 @@ void ClassLoaderData::verify() { if (_modules != NULL) { _modules->verify(); } + + if (_deallocate_list != nullptr) { + for (int i = _deallocate_list->length() - 1; i >= 0; i--) { + Metadata* m = _deallocate_list->at(i); + if (m->is_klass()) { + ((Klass*)m)->verify(); + } + } + } + + // Check the oops in the handles area + VerifyHandleOops vho; + oops_do(&vho, _claim_none, false); } bool ClassLoaderData::contains_klass(Klass* klass) { diff --git a/src/hotspot/share/classfile/classLoaderDataShared.cpp b/src/hotspot/share/classfile/classLoaderDataShared.cpp index 7954e643c67..92532427446 100644 --- a/src/hotspot/share/classfile/classLoaderDataShared.cpp +++ b/src/hotspot/share/classfile/classLoaderDataShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -54,7 +54,6 @@ class ArchivedClassLoaderData { void iterate_symbols(ClassLoaderData* loader_data, MetaspaceClosure* closure); void allocate(ClassLoaderData* loader_data); void init_archived_entries(ClassLoaderData* loader_data); - void init_archived_oops(ClassLoaderData* loader_data); void serialize(SerializeClosure* f) { f->do_ptr((void**)&_packages); @@ -101,14 +100,6 @@ void ArchivedClassLoaderData::init_archived_entries(ClassLoaderData* loader_data } } -void ArchivedClassLoaderData::init_archived_oops(ClassLoaderData* loader_data) { - assert(DumpSharedSpaces, "must be"); - assert_valid(loader_data); - if (loader_data != NULL) { - loader_data->modules()->init_archived_oops(_modules); - } -} - void ArchivedClassLoaderData::restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops) { assert(UseSharedSpaces, "must be"); assert_valid(loader_data); @@ -174,13 +165,6 @@ void ClassLoaderDataShared::init_archived_tables() { _archived_javabase_moduleEntry = ModuleEntry::get_archived_entry(ModuleEntryTable::javabase_moduleEntry()); } -void ClassLoaderDataShared::init_archived_oops() { - assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); - _archived_boot_loader_data.init_archived_oops (null_class_loader_data()); - _archived_platform_loader_data.init_archived_oops(java_platform_loader_data_or_null()); - _archived_system_loader_data.init_archived_oops (java_system_loader_data_or_null()); -} - void ClassLoaderDataShared::serialize(SerializeClosure* f) { _archived_boot_loader_data.serialize(f); _archived_platform_loader_data.serialize(f); diff --git a/src/hotspot/share/classfile/classLoaderDataShared.hpp b/src/hotspot/share/classfile/classLoaderDataShared.hpp index f5272f8d59f..957c705afde 100644 --- a/src/hotspot/share/classfile/classLoaderDataShared.hpp +++ b/src/hotspot/share/classfile/classLoaderDataShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -38,7 +38,6 @@ class ClassLoaderDataShared : AllStatic { static void allocate_archived_tables(); static void iterate_symbols(MetaspaceClosure* closure); static void init_archived_tables(); - static void init_archived_oops(); static void serialize(SerializeClosure* f); static void clear_archived_oops(); static oop restore_archived_oops_for_null_class_loader_data(); diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 0e523cac6e3..4b16bc7e526 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1683,7 +1683,7 @@ int java_lang_Thread::_interrupted_offset; int java_lang_Thread::_tid_offset; int java_lang_Thread::_continuation_offset; int java_lang_Thread::_park_blocker_offset; -int java_lang_Thread::_extentLocalBindings_offset; +int java_lang_Thread::_scopedValueBindings_offset; JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;) #define THREAD_FIELDS_DO(macro) \ @@ -1696,7 +1696,7 @@ JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;) macro(_tid_offset, k, "tid", long_signature, false); \ macro(_park_blocker_offset, k, "parkBlocker", object_signature, false); \ macro(_continuation_offset, k, "cont", continuation_signature, false); \ - macro(_extentLocalBindings_offset, k, "extentLocalBindings", object_signature, false); + macro(_scopedValueBindings_offset, k, "scopedValueBindings", object_signature, false); void java_lang_Thread::compute_offsets() { assert(_holder_offset == 0, "offsets should be initialized only once"); @@ -1714,7 +1714,7 @@ void java_lang_Thread::serialize_offsets(SerializeClosure* f) { #endif JavaThread* java_lang_Thread::thread(oop java_thread) { - return (JavaThread*)java_thread->address_field(_eetop_offset); + return reinterpret_cast(java_thread->address_field(_eetop_offset)); } void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) { @@ -1729,8 +1729,9 @@ void java_lang_Thread::set_jvmti_thread_state(oop java_thread, JvmtiThreadState* java_thread->address_field_put(_jvmti_thread_state_offset, (address)state); } -void java_lang_Thread::clear_extentLocalBindings(oop java_thread) { - java_thread->obj_field_put(_extentLocalBindings_offset, NULL); +void java_lang_Thread::clear_scopedValueBindings(oop java_thread) { + assert(java_thread != NULL, "need a java_lang_Thread pointer here"); + java_thread->obj_field_put(_scopedValueBindings_offset, NULL); } oop java_lang_Thread::holder(oop java_thread) { @@ -2491,17 +2492,18 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } // Allocate temporary buffer with extra space for formatting and line number - char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + const size_t buf_size = buf_len + 64; + char* buf = NEW_RESOURCE_ARRAY(char, buf_size); // Print stack trace line in buffer - sprintf(buf, "\tat %s.%s(", klass_name, method_name); + size_t buf_off = os::snprintf_checked(buf, buf_size, "\tat %s.%s(", klass_name, method_name); // Print module information if (module_name != NULL) { if (module_version != NULL) { - sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s@%s/", module_name, module_version); } else { - sprintf(buf + (int)strlen(buf), "%s/", module_name); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s/", module_name); } } @@ -2516,17 +2518,17 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } else { if (source_file_name != NULL && (line_number != -1)) { // Sourcename and linenumber - sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s:%d)", source_file_name, line_number); } else if (source_file_name != NULL) { // Just sourcename - sprintf(buf + (int)strlen(buf), "%s)", source_file_name); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s)", source_file_name); } else { // Neither sourcename nor linenumber - sprintf(buf + (int)strlen(buf), "Unknown Source)"); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "Unknown Source)"); } CompiledMethod* nm = method->code(); if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + os::snprintf_checked(buf + buf_off, buf_size - buf_off, "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); } } } @@ -4131,17 +4133,17 @@ int jdk_internal_foreign_abi_ABIDescriptor::_outputStorage_offset; int jdk_internal_foreign_abi_ABIDescriptor::_volatileStorage_offset; int jdk_internal_foreign_abi_ABIDescriptor::_stackAlignment_offset; int jdk_internal_foreign_abi_ABIDescriptor::_shadowSpace_offset; -int jdk_internal_foreign_abi_ABIDescriptor::_targetAddrStorage_offset; -int jdk_internal_foreign_abi_ABIDescriptor::_retBufAddrStorage_offset; +int jdk_internal_foreign_abi_ABIDescriptor::_scratch1_offset; +int jdk_internal_foreign_abi_ABIDescriptor::_scratch2_offset; #define ABIDescriptor_FIELDS_DO(macro) \ - macro(_inputStorage_offset, k, "inputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_outputStorage_offset, k, "outputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_volatileStorage_offset, k, "volatileStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_stackAlignment_offset, k, "stackAlignment", int_signature, false); \ - macro(_shadowSpace_offset, k, "shadowSpace", int_signature, false); \ - macro(_targetAddrStorage_offset, k, "targetAddrStorage", jdk_internal_foreign_abi_VMStorage_signature, false); \ - macro(_retBufAddrStorage_offset, k, "retBufAddrStorage", jdk_internal_foreign_abi_VMStorage_signature, false); + macro(_inputStorage_offset, k, "inputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_outputStorage_offset, k, "outputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_volatileStorage_offset, k, "volatileStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_stackAlignment_offset, k, "stackAlignment", int_signature, false); \ + macro(_shadowSpace_offset, k, "shadowSpace", int_signature, false); \ + macro(_scratch1_offset, k, "scratch1", jdk_internal_foreign_abi_VMStorage_signature, false); \ + macro(_scratch2_offset, k, "scratch2", jdk_internal_foreign_abi_VMStorage_signature, false); bool jdk_internal_foreign_abi_ABIDescriptor::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -4178,22 +4180,24 @@ jint jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(oop entry) { return entry->int_field(_shadowSpace_offset); } -oop jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(oop entry) { - return entry->obj_field(_targetAddrStorage_offset); +oop jdk_internal_foreign_abi_ABIDescriptor::scratch1(oop entry) { + return entry->obj_field(_scratch1_offset); } -oop jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(oop entry) { - return entry->obj_field(_retBufAddrStorage_offset); +oop jdk_internal_foreign_abi_ABIDescriptor::scratch2(oop entry) { + return entry->obj_field(_scratch2_offset); } int jdk_internal_foreign_abi_VMStorage::_type_offset; -int jdk_internal_foreign_abi_VMStorage::_index_offset; +int jdk_internal_foreign_abi_VMStorage::_indexOrOffset_offset; +int jdk_internal_foreign_abi_VMStorage::_segmentMaskOrSize_offset; int jdk_internal_foreign_abi_VMStorage::_debugName_offset; #define VMStorage_FIELDS_DO(macro) \ - macro(_type_offset, k, "type", int_signature, false); \ - macro(_index_offset, k, "index", int_signature, false); \ - macro(_debugName_offset, k, "debugName", string_signature, false); \ + macro(_type_offset, k, "type", byte_signature, false); \ + macro(_indexOrOffset_offset, k, "indexOrOffset", int_signature, false); \ + macro(_segmentMaskOrSize_offset, k, "segmentMaskOrSize", short_signature, false); \ + macro(_debugName_offset, k, "debugName", string_signature, false); \ bool jdk_internal_foreign_abi_VMStorage::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -4210,12 +4214,16 @@ void jdk_internal_foreign_abi_VMStorage::serialize_offsets(SerializeClosure* f) } #endif -jint jdk_internal_foreign_abi_VMStorage::type(oop entry) { - return entry->int_field(_type_offset); +jbyte jdk_internal_foreign_abi_VMStorage::type(oop entry) { + return entry->byte_field(_type_offset); } -jint jdk_internal_foreign_abi_VMStorage::index(oop entry) { - return entry->int_field(_index_offset); +jint jdk_internal_foreign_abi_VMStorage::index_or_offset(oop entry) { + return entry->int_field(_indexOrOffset_offset); +} + +jshort jdk_internal_foreign_abi_VMStorage::segment_mask_or_size(oop entry) { + return entry->short_field(_segmentMaskOrSize_offset); } oop jdk_internal_foreign_abi_VMStorage::debugName(oop entry) { diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 9c55961cb43..39e12710b06 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -352,7 +352,7 @@ class java_lang_Thread : AllStatic { static int _tid_offset; static int _continuation_offset; static int _park_blocker_offset; - static int _extentLocalBindings_offset; + static int _scopedValueBindings_offset; JFR_ONLY(static int _jfr_epoch_offset;) static void compute_offsets(); @@ -398,8 +398,8 @@ class java_lang_Thread : AllStatic { static JvmtiThreadState* jvmti_thread_state(oop java_thread); static void set_jvmti_thread_state(oop java_thread, JvmtiThreadState* state); - // Clear all extent local bindings on error - static void clear_extentLocalBindings(oop java_thread); + // Clear all scoped value bindings on error + static void clear_scopedValueBindings(oop java_thread); // Blocker object responsible for thread parking static oop park_blocker(oop java_thread); @@ -952,6 +952,7 @@ class java_lang_ref_Reference: AllStatic { static inline oop phantom_referent_no_keepalive(oop ref); static inline oop unknown_referent_no_keepalive(oop ref); static inline void clear_referent(oop ref); + static inline void clear_referent_raw(oop ref); static inline HeapWord* referent_addr_raw(oop ref); static inline oop next(oop ref); static inline void set_next(oop ref, oop value); @@ -1121,8 +1122,8 @@ class jdk_internal_foreign_abi_ABIDescriptor: AllStatic { static int _volatileStorage_offset; static int _stackAlignment_offset; static int _shadowSpace_offset; - static int _targetAddrStorage_offset; - static int _retBufAddrStorage_offset; + static int _scratch1_offset; + static int _scratch2_offset; static void compute_offsets(); @@ -1135,8 +1136,8 @@ class jdk_internal_foreign_abi_ABIDescriptor: AllStatic { static objArrayOop volatileStorage(oop entry); static jint stackAlignment(oop entry); static jint shadowSpace(oop entry); - static oop targetAddrStorage(oop entry); - static oop retBufAddrStorage(oop entry); + static oop scratch1(oop entry); + static oop scratch2(oop entry); // Testers static bool is_subclass(Klass* klass) { @@ -1151,7 +1152,8 @@ class jdk_internal_foreign_abi_VMStorage: AllStatic { private: static int _type_offset; - static int _index_offset; + static int _indexOrOffset_offset; + static int _segmentMaskOrSize_offset; static int _debugName_offset; static void compute_offsets(); @@ -1160,9 +1162,10 @@ class jdk_internal_foreign_abi_VMStorage: AllStatic { static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; // Accessors - static jint type(oop entry); - static jint index(oop entry); - static oop debugName(oop entry); + static jbyte type(oop entry); + static jint index_or_offset(oop entry); + static jshort segment_mask_or_size(oop entry); + static oop debugName(oop entry); // Testers static bool is_subclass(Klass* klass) { @@ -1291,9 +1294,6 @@ class java_lang_invoke_MemberName: AllStatic { MN_TRUSTED_FINAL = 0x00200000, // trusted final field MN_REFERENCE_KIND_SHIFT = 24, // refKind MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, - // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers: - MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes - MN_SEARCH_INTERFACES = 0x00200000, // walk implemented interfaces MN_NESTMATE_CLASS = 0x00000001, MN_HIDDEN_CLASS = 0x00000002, MN_STRONG_LOADER_LINK = 0x00000004, diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp index 1f0b5f42796..386f3094279 100644 --- a/src/hotspot/share/classfile/javaClasses.inline.hpp +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp @@ -152,6 +152,10 @@ oop java_lang_ref_Reference::unknown_referent_no_keepalive(oop ref) { } void java_lang_ref_Reference::clear_referent(oop ref) { + HeapAccess::oop_store_at(ref, _referent_offset, nullptr); +} + +void java_lang_ref_Reference::clear_referent_raw(oop ref) { ref->obj_field_put_raw(_referent_offset, nullptr); } diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index 26bf3e7911e..32ac2e07d00 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -47,11 +47,11 @@ class LoaderConstraint : public CHeapObj { // not class loaders. GrowableArray* _loaders; // initiating loaders public: - LoaderConstraint(InstanceKlass* klass, oop class_loader1, oop class_loader2) : + LoaderConstraint(InstanceKlass* klass, ClassLoaderData* loader1, ClassLoaderData* loader2) : _klass(klass) { _loaders = new (mtClass) GrowableArray(10, mtClass); - add_loader(class_loader1); - add_loader(class_loader2); + add_loader_data(loader1); + add_loader_data(loader2); } LoaderConstraint(const LoaderConstraint& src) = delete; LoaderConstraint& operator=(const LoaderConstraint&) = delete; @@ -61,7 +61,7 @@ class LoaderConstraint : public CHeapObj { InstanceKlass* klass() const { return _klass; } void set_klass(InstanceKlass* k) { _klass = k; } - void extend_loader_constraint(Symbol* class_name, Handle loader, InstanceKlass* klass); + void extend_loader_constraint(Symbol* class_name, ClassLoaderData* loader, InstanceKlass* klass); int num_loaders() const { return _loaders->length(); } ClassLoaderData* loader_data(int i) { return _loaders->at(i); } @@ -71,11 +71,6 @@ class LoaderConstraint : public CHeapObj { assert(_loaders->at(n)->is_unloading(), "should be unloading"); _loaders->remove_at(n); } - - // convenience - void add_loader(oop p) { - _loaders->push(ClassLoaderData::class_loader_data(p)); - } }; // For this class name, these are the set of LoaderConstraints for classes loaded with this name. @@ -114,15 +109,15 @@ class ConstraintSet { // copied into hashtable as ResourceHashtable _loader_constraint_table; void LoaderConstraint::extend_loader_constraint(Symbol* class_name, - Handle loader, + ClassLoaderData* loader, InstanceKlass* klass) { - add_loader(loader()); + add_loader_data(loader); LogTarget(Info, class, loader, constraints) lt; if (lt.is_enabled()) { ResourceMark rm; lt.print("extending constraint for name %s by adding loader: %s %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id(), + loader->loader_name_and_id(), _klass == NULL ? " and setting class object" : ""); } if (_klass == NULL) { @@ -137,7 +132,7 @@ void LoaderConstraint::extend_loader_constraint(Symbol* class_name, // entries in the table could be being dynamically resized. LoaderConstraint* LoaderConstraintTable::find_loader_constraint( - Symbol* name, Handle loader) { + Symbol* name, ClassLoaderData* loader_data) { assert_lock_strong(SystemDictionary_lock); ConstraintSet* set = _loader_constraint_table.get(name); @@ -145,8 +140,6 @@ LoaderConstraint* LoaderConstraintTable::find_loader_constraint( return nullptr; } - ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader()); - for (int i = 0; i < set->num_constraints(); i++) { LoaderConstraint* p = set->constraint_at(i); for (int i = p->num_loaders() - 1; i >= 0; i--) { @@ -162,9 +155,10 @@ LoaderConstraint* LoaderConstraintTable::find_loader_constraint( } // Either add it to an existing entry in the table or make a new one. -void LoaderConstraintTable::add_loader_constraint(Symbol* name, InstanceKlass* klass, oop class_loader1, oop class_loader2) { +void LoaderConstraintTable::add_loader_constraint(Symbol* name, InstanceKlass* klass, + ClassLoaderData* loader1, ClassLoaderData* loader2) { assert_lock_strong(SystemDictionary_lock); - LoaderConstraint* constraint = new LoaderConstraint(klass, class_loader1, class_loader2); + LoaderConstraint* constraint = new LoaderConstraint(klass, loader1, loader2); // The klass may be null if it hasn't been loaded yet, for instance while checking // a parameter name to a method call. We impose this constraint that the @@ -256,22 +250,22 @@ void LoaderConstraintTable::purge_loader_constraints() { } void log_ldr_constraint_msg(Symbol* class_name, const char* reason, - Handle class_loader1, Handle class_loader2) { + ClassLoaderData* loader1, ClassLoaderData* loader2) { LogTarget(Info, class, loader, constraints) lt; if (lt.is_enabled()) { ResourceMark rm; lt.print("Failed to add constraint for name: %s, loader[0]: %s," " loader[1]: %s, Reason: %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id(), - ClassLoaderData::class_loader_data(class_loader2())->loader_name_and_id(), + loader1->loader_name_and_id(), + loader2->loader_name_and_id(), reason); } } bool LoaderConstraintTable::add_entry(Symbol* class_name, - InstanceKlass* klass1, Handle class_loader1, - InstanceKlass* klass2, Handle class_loader2) { + InstanceKlass* klass1, ClassLoaderData* loader1, + InstanceKlass* klass2, ClassLoaderData* loader2) { LogTarget(Info, class, loader, constraints) lt; if (klass1 != NULL && klass2 != NULL) { @@ -282,20 +276,20 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, log_ldr_constraint_msg(class_name, "The class objects presented by loader[0] and loader[1] " "are different", - class_loader1, class_loader2); + loader1, loader2); return false; } } InstanceKlass* klass = klass1 != NULL ? klass1 : klass2; - LoaderConstraint* pp1 = find_loader_constraint(class_name, class_loader1); + LoaderConstraint* pp1 = find_loader_constraint(class_name, loader1); if (pp1 != NULL && pp1->klass() != NULL) { if (klass != NULL) { if (klass != pp1->klass()) { log_ldr_constraint_msg(class_name, "The class object presented by loader[0] does not match " "the stored class object in the constraint", - class_loader1, class_loader2); + loader1, loader2); return false; } } else { @@ -303,14 +297,14 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, } } - LoaderConstraint* pp2 = find_loader_constraint(class_name, class_loader2); + LoaderConstraint* pp2 = find_loader_constraint(class_name, loader2); if (pp2 != NULL && pp2->klass() != NULL) { if (klass != NULL) { if (klass != pp2->klass()) { log_ldr_constraint_msg(class_name, "The class object presented by loader[1] does not match " "the stored class object in the constraint", - class_loader1, class_loader2); + loader1, loader2); return false; } } else { @@ -320,15 +314,14 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, if (pp1 == NULL && pp2 == NULL) { - add_loader_constraint(class_name, klass, class_loader1(), class_loader2()); + add_loader_constraint(class_name, klass, loader1, loader2); if (lt.is_enabled()) { ResourceMark rm; lt.print("adding new constraint for name: %s, loader[0]: %s," " loader[1]: %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id(), - ClassLoaderData::class_loader_data(class_loader2())->loader_name_and_id() - ); + loader1->loader_name_and_id(), + loader2->loader_name_and_id()); } } else if (pp1 == pp2) { /* constraint already imposed */ @@ -339,16 +332,15 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, lt.print("setting class object in existing constraint for" " name: %s and loader %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id() - ); + loader1->loader_name_and_id()); } } else { assert(pp1->klass() == klass, "loader constraints corrupted"); } } else if (pp1 == NULL) { - pp2->extend_loader_constraint(class_name, class_loader1, klass); + pp2->extend_loader_constraint(class_name, loader1, klass); } else if (pp2 == NULL) { - pp1->extend_loader_constraint(class_name, class_loader2, klass); + pp1->extend_loader_constraint(class_name, loader1, klass); } else { merge_loader_constraints(class_name, pp1, pp2, klass); } @@ -359,7 +351,7 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, // return true if the constraint was updated, false if the constraint is // violated bool LoaderConstraintTable::check_or_update(InstanceKlass* k, - Handle loader, + ClassLoaderData* loader, Symbol* name) { LogTarget(Info, class, loader, constraints) lt; LoaderConstraint* p = find_loader_constraint(name, loader); @@ -369,7 +361,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, lt.print("constraint check failed for name %s, loader %s: " "the presented class object differs from that stored", name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id()); + loader->loader_name_and_id()); } return false; } else { @@ -380,7 +372,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, lt.print("updating constraint for name %s, loader %s, " "by setting class object", name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id()); + loader->loader_name_and_id()); } } return true; @@ -388,7 +380,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, } InstanceKlass* LoaderConstraintTable::find_constrained_klass(Symbol* name, - Handle loader) { + ClassLoaderData* loader) { LoaderConstraint *p = find_loader_constraint(name, loader); if (p != NULL && p->klass() != NULL) { assert(p->klass()->is_instance_klass(), "sanity"); diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp index c97de342cc6..c3fc93b6522 100644 --- a/src/hotspot/share/classfile/loaderConstraints.hpp +++ b/src/hotspot/share/classfile/loaderConstraints.hpp @@ -35,17 +35,18 @@ class Symbol; class LoaderConstraintTable : public AllStatic { private: - static LoaderConstraint* find_loader_constraint(Symbol* name, Handle loader); + static LoaderConstraint* find_loader_constraint(Symbol* name, ClassLoaderData* loader); - static void add_loader_constraint(Symbol* name, InstanceKlass* klass, oop class_loader1, oop class_loader2); + static void add_loader_constraint(Symbol* name, InstanceKlass* klass, + ClassLoaderData* loader1, ClassLoaderData* loader2); static void merge_loader_constraints(Symbol* class_name, LoaderConstraint* pp1, LoaderConstraint* pp2, InstanceKlass* klass); public: // Check class loader constraints - static bool add_entry(Symbol* name, InstanceKlass* klass1, Handle loader1, - InstanceKlass* klass2, Handle loader2); + static bool add_entry(Symbol* name, InstanceKlass* klass1, ClassLoaderData* loader1, + InstanceKlass* klass2, ClassLoaderData* loader2); // Note: The main entry point for this module is via SystemDictionary. // SystemDictionary::check_signature_loaders(Symbol* signature, @@ -53,10 +54,10 @@ class LoaderConstraintTable : public AllStatic { // Handle loader1, Handle loader2, // bool is_method) - static InstanceKlass* find_constrained_klass(Symbol* name, Handle loader); + static InstanceKlass* find_constrained_klass(Symbol* name, ClassLoaderData* loader); // Class loader constraints - static bool check_or_update(InstanceKlass* k, Handle loader, Symbol* name); + static bool check_or_update(InstanceKlass* k, ClassLoaderData* loader, Symbol* name); static void purge_loader_constraints(); diff --git a/src/hotspot/share/classfile/moduleEntry.cpp b/src/hotspot/share/classfile/moduleEntry.cpp index 67ca698c09c..28f865be2aa 100644 --- a/src/hotspot/share/classfile/moduleEntry.cpp +++ b/src/hotspot/share/classfile/moduleEntry.cpp @@ -31,8 +31,10 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" +#include "classfile/systemDictionary.hpp" #include "jni.h" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/oopHandle.inline.hpp" @@ -386,20 +388,38 @@ typedef ResourceHashtable< AnyObj::C_HEAP> ArchivedModuleEntries; static ArchivedModuleEntries* _archive_modules_entries = NULL; +#ifndef PRODUCT +static int _num_archived_module_entries = 0; +static int _num_inited_module_entries = 0; +#endif + ModuleEntry* ModuleEntry::allocate_archived_entry() const { assert(is_named(), "unnamed packages/modules are not archived"); ModuleEntry* archived_entry = (ModuleEntry*)ArchiveBuilder::rw_region_alloc(sizeof(ModuleEntry)); memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); + archived_entry->_archived_module_index = -1; if (_archive_modules_entries == NULL) { _archive_modules_entries = new (mtClass)ArchivedModuleEntries(); } assert(_archive_modules_entries->get(this) == NULL, "Each ModuleEntry must not be shared across ModuleEntryTables"); _archive_modules_entries->put(this, archived_entry); + DEBUG_ONLY(_num_archived_module_entries++); + if (log_is_enabled(Info, cds, module)) { + ResourceMark rm; + LogStream ls(Log(cds, module)::info()); + ls.print("Stored in archive: "); + archived_entry->print(&ls); + } return archived_entry; } +bool ModuleEntry::has_been_archived() { + assert(!ArchiveBuilder::current()->is_in_buffer_space(this), "must be called on original ModuleEntry"); + return _archive_modules_entries->contains(this); +} + ModuleEntry* ModuleEntry::get_archived_entry(ModuleEntry* orig_entry) { ModuleEntry** ptr = _archive_modules_entries->get(orig_entry); assert(ptr != NULL && *ptr != NULL, "must have been allocated"); @@ -467,27 +487,39 @@ void ModuleEntry::init_as_archived_entry() { ArchivePtrMarker::mark_pointer((address*)&_location); } -void ModuleEntry::init_archived_oops() { +void ModuleEntry::update_oops_in_archived_module(int root_oop_index) { assert(DumpSharedSpaces, "static dump only"); - oop module_obj = module(); - if (module_obj != NULL) { - oop m = HeapShared::find_archived_heap_object(module_obj); - assert(m != NULL, "sanity"); - _archived_module_index = HeapShared::append_root(m); - } + assert(_archived_module_index == -1, "must be set exactly once"); + assert(root_oop_index >= 0, "sanity"); + + _archived_module_index = root_oop_index; + assert(shared_protection_domain() == NULL, "never set during -Xshare:dump"); // Clear handles and restore at run time. Handles cannot be archived. OopHandle null_handle; _module = null_handle; + + // For verify_archived_module_entries() + DEBUG_ONLY(_num_inited_module_entries++); } +#ifndef PRODUCT +void ModuleEntry::verify_archived_module_entries() { + assert(_num_archived_module_entries == _num_inited_module_entries, + "%d ModuleEntries have been archived but %d of them have been properly initialized with archived java.lang.Module objects", + _num_archived_module_entries, _num_inited_module_entries); +} +#endif // PRODUCT + void ModuleEntry::load_from_archive(ClassLoaderData* loader_data) { + assert(UseSharedSpaces, "runtime only"); set_loader_data(loader_data); _reads = restore_growable_array((Array*)_reads); JFR_ONLY(INIT_ID(this);) } void ModuleEntry::restore_archived_oops(ClassLoaderData* loader_data) { + assert(UseSharedSpaces, "runtime only"); Handle module_handle(Thread::current(), HeapShared::get_root(_archived_module_index, /*clear=*/true)); assert(module_handle.not_null(), "huh"); set_module(loader_data->add_handle(module_handle)); @@ -496,12 +528,19 @@ void ModuleEntry::restore_archived_oops(ClassLoaderData* loader_data) { // because it may be affected by archive relocation. java_lang_Module::set_module_entry(module_handle(), this); - if (loader_data->class_loader() != NULL) { - java_lang_Module::set_loader(module_handle(), loader_data->class_loader()); + assert(java_lang_Module::loader(module_handle()) == loader_data->class_loader(), + "must be set in dump time"); + + if (log_is_enabled(Info, cds, module)) { + ResourceMark rm; + LogStream ls(Log(cds, module)::info()); + ls.print("Restored from archive: "); + print(&ls); } } void ModuleEntry::clear_archived_oops() { + assert(UseSharedSpaces, "runtime only"); HeapShared::clear_root(_archived_module_index); } @@ -544,14 +583,6 @@ void ModuleEntryTable::init_archived_entries(Array* archived_modul } } -void ModuleEntryTable::init_archived_oops(Array* archived_modules) { - assert(DumpSharedSpaces, "dump time only"); - for (int i = 0; i < archived_modules->length(); i++) { - ModuleEntry* archived_entry = archived_modules->at(i); - archived_entry->init_archived_oops(); - } -} - void ModuleEntryTable::load_archived_entries(ClassLoaderData* loader_data, Array* archived_modules) { assert(UseSharedSpaces, "runtime only"); diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index 1d8dfc35908..45973c9d833 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -175,13 +175,15 @@ class ModuleEntry : public CHeapObj { void iterate_symbols(MetaspaceClosure* closure); ModuleEntry* allocate_archived_entry() const; void init_as_archived_entry(); - void init_archived_oops(); static ModuleEntry* get_archived_entry(ModuleEntry* orig_entry); + bool has_been_archived(); static Array* write_growable_array(GrowableArray* array); static GrowableArray* restore_growable_array(Array* archived_array); void load_from_archive(ClassLoaderData* loader_data); void restore_archived_oops(ClassLoaderData* loader_data); void clear_archived_oops(); + void update_oops_in_archived_module(int root_oop_index); + static void verify_archived_module_entries() PRODUCT_RETURN; #endif }; @@ -250,7 +252,6 @@ class ModuleEntryTable : public CHeapObj { void iterate_symbols(MetaspaceClosure* closure); Array* allocate_archived_entries(); void init_archived_entries(Array* archived_modules); - void init_archived_oops(Array* archived_modules); void load_archived_entries(ClassLoaderData* loader_data, Array* archived_modules); void restore_archived_oops(ClassLoaderData* loader_data, diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index c37dee82a42..027ecc646fc 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -477,6 +477,88 @@ void Modules::define_module(Handle module, jboolean is_open, jstring version, } #if INCLUDE_CDS_JAVA_HEAP +static bool _seen_platform_unnamed_module = false; +static bool _seen_system_unnamed_module = false; + +// Validate the states of an java.lang.Module oop to be archived. +// +// Returns true iff the oop has an archived ModuleEntry. +bool Modules::check_module_oop(oop orig_module_obj) { + assert(DumpSharedSpaces, "must be"); + assert(MetaspaceShared::use_full_module_graph(), "must be"); + assert(java_lang_Module::is_instance(orig_module_obj), "must be"); + + ModuleEntry* orig_module_ent = java_lang_Module::module_entry_raw(orig_module_obj); + if (orig_module_ent == nullptr) { + // These special java.lang.Module oops are created in Java code. They are not + // defined via Modules::define_module(), so they don't have a ModuleEntry: + // java.lang.Module::ALL_UNNAMED_MODULE + // java.lang.Module::EVERYONE_MODULE + // jdk.internal.loader.ClassLoaders$BootClassLoader::unnamedModule + log_info(cds, module)("Archived java.lang.Module oop " PTR_FORMAT " with no ModuleEntry*", p2i(orig_module_obj)); + assert(java_lang_Module::name(orig_module_obj) == nullptr, "must be unnamed"); + return false; + } else { + // This java.lang.Module oop has an ModuleEntry*. Check if the latter is archived. + if (log_is_enabled(Info, cds, module)) { + ResourceMark rm; + LogStream ls(Log(cds, module)::info()); + ls.print("Archived java.lang.Module oop " PTR_FORMAT " for ", p2i(orig_module_obj)); + orig_module_ent->print(&ls); + } + + // We only archive the default module graph, which should contain only java.lang.Module oops + // for the 3 built-in loaders (boot/platform/system) + ClassLoaderData* loader_data = orig_module_ent->loader_data(); + assert(loader_data->is_builtin_class_loader_data(), "must be"); + + if (orig_module_ent->name() != nullptr) { + // For each named module, we archive both the java.lang.Module oop and the ModuleEntry. + assert(orig_module_ent->has_been_archived(), "sanity"); + return true; + } else { + // We only archive two unnamed module oops (for platform and system loaders). These do NOT have an archived + // ModuleEntry. + // + // At runtime, these oops are fetched from java_lang_ClassLoader::unnamedModule(loader) and + // are initialized in ClassLoaderData::ClassLoaderData() => ModuleEntry::create_unnamed_module(), where + // a new ModuleEntry is allocated. + assert(!loader_data->is_boot_class_loader_data(), "unnamed module for boot loader should be not archived"); + assert(!orig_module_ent->has_been_archived(), "sanity"); + + if (SystemDictionary::is_platform_class_loader(loader_data->class_loader())) { + assert(!_seen_platform_unnamed_module, "only once"); + _seen_platform_unnamed_module = true; + } else if (SystemDictionary::is_system_class_loader(loader_data->class_loader())) { + assert(!_seen_system_unnamed_module, "only once"); + _seen_system_unnamed_module = true; + } else { + // The java.lang.Module oop and ModuleEntry of the unnamed module of the boot loader are + // not in the archived module graph. These are always allocated at runtime. + ShouldNotReachHere(); + } + return false; + } + } +} + +void Modules::update_oops_in_archived_module(oop orig_module_obj, int archived_module_root_index) { + // This java.lang.Module oop must have an archived ModuleEntry + assert(check_module_oop(orig_module_obj) == true, "sanity"); + + // We remember the oop inside the ModuleEntry::_archived_module_index. At runtime, we use + // this index to reinitialize the ModuleEntry inside ModuleEntry::restore_archived_oops(). + // + // ModuleEntry::verify_archived_module_entries(), called below, ensures that every archived + // ModuleEntry has been assigned an _archived_module_index. + ModuleEntry* orig_module_ent = java_lang_Module::module_entry_raw(orig_module_obj); + ModuleEntry::get_archived_entry(orig_module_ent)->update_oops_in_archived_module(archived_module_root_index); +} + +void Modules::verify_archived_modules() { + ModuleEntry::verify_archived_module_entries(); +} + void Modules::define_archived_modules(Handle h_platform_loader, Handle h_system_loader, TRAPS) { assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); diff --git a/src/hotspot/share/classfile/modules.hpp b/src/hotspot/share/classfile/modules.hpp index 5c52a323b0c..d444ea3bb82 100644 --- a/src/hotspot/share/classfile/modules.hpp +++ b/src/hotspot/share/classfile/modules.hpp @@ -53,8 +53,12 @@ class Modules : AllStatic { static void define_module(Handle module, jboolean is_open, jstring version, jstring location, jobjectArray packages, TRAPS); + static bool check_module_oop(oop orig_module_obj) NOT_CDS_JAVA_HEAP_RETURN_(false); + static void update_oops_in_archived_module(oop orig_module_obj, int archived_module_root_index) + NOT_CDS_JAVA_HEAP_RETURN; static void define_archived_modules(Handle h_platform_loader, Handle h_system_loader, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static void verify_archived_modules() NOT_CDS_JAVA_HEAP_RETURN; // Provides the java.lang.Module for the unnamed module defined // to the boot loader. diff --git a/src/hotspot/share/classfile/placeholders.hpp b/src/hotspot/share/classfile/placeholders.hpp index 4e05136e00b..c44e3897b39 100644 --- a/src/hotspot/share/classfile/placeholders.hpp +++ b/src/hotspot/share/classfile/placeholders.hpp @@ -105,9 +105,11 @@ class PlaceholderEntry { Symbol* supername() const { return _supername; } void set_supername(Symbol* supername) { - Symbol::maybe_decrement_refcount(_supername); - _supername = supername; - Symbol::maybe_increment_refcount(_supername); + if (supername != _supername) { + Symbol::maybe_decrement_refcount(_supername); + _supername = supername; + Symbol::maybe_increment_refcount(_supername); + } } void clear_supername() { Symbol::maybe_decrement_refcount(_supername); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index ea878c54bc7..2916c8db35e 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -180,6 +180,11 @@ oop SystemDictionary::get_platform_class_loader_impl(TRAPS) { return result.get_oop(); } +// Helper function +inline ClassLoaderData* class_loader_data(Handle class_loader) { + return ClassLoaderData::class_loader_data(class_loader()); +} + ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool create_mirror_cld) { if (create_mirror_cld) { // Add a new class loader data to the graph. @@ -1064,7 +1069,7 @@ bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name, // Need to reload it now. TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name); if (pkg_name != NULL) { - pkg_entry = ClassLoaderData::class_loader_data(class_loader())->packages()->lookup_only(pkg_name); + pkg_entry = class_loader_data(class_loader)->packages()->lookup_only(pkg_name); } } @@ -1180,7 +1185,7 @@ InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* i // The lambda proxy class and its nest host have the same class loader and class loader data, // as verified in SystemDictionaryShared::add_lambda_proxy_class() assert(shared_nest_host->class_loader() == class_loader(), "mismatched class loader"); - assert(shared_nest_host->class_loader_data() == ClassLoaderData::class_loader_data(class_loader()), "mismatched class loader data"); + assert(shared_nest_host->class_loader_data() == class_loader_data(class_loader), "mismatched class loader data"); ik->set_nest_host(shared_nest_host); return loaded_ik; @@ -1228,7 +1233,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, // loaders, including the bootstrap loader via the placeholder table, // this lock is currently a nop. - ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); + ClassLoaderData* loader_data = class_loader_data(class_loader); { HandleMark hm(THREAD); Handle lockObject = get_loader_lock_or_null(class_loader); @@ -1264,12 +1269,11 @@ InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Ha ResourceMark rm(THREAD); PackageEntry* pkg_entry = NULL; bool search_only_bootloader_append = false; - ClassLoaderData *loader_data = class_loader_data(class_loader); // Find the package in the boot loader's package entry table. TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name); if (pkg_name != NULL) { - pkg_entry = loader_data->packages()->lookup_only(pkg_name); + pkg_entry = class_loader_data(class_loader)->packages()->lookup_only(pkg_name); } // Prior to attempting to load the class, enforce the boot loader's @@ -1410,22 +1414,22 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* name, // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. if (loaded_class != NULL && - loaded_class->class_loader() != class_loader()) { + loaded_class->class_loader() != class_loader()) { - check_constraints(loaded_class, class_loader, false, CHECK_NULL); + ClassLoaderData* loader_data = class_loader_data(class_loader); + check_constraints(loaded_class, loader_data, false, CHECK_NULL); // Record dependency for non-parent delegation. // This recording keeps the defining class loader of the klass (loaded_class) found // from being unloaded while the initiating class loader is loaded // even if the reference to the defining class loader is dropped // before references to the initiating class loader. - ClassLoaderData* loader_data = class_loader_data(class_loader); loader_data->record_dependency(loaded_class); { // Grabbing the Compile_lock prevents systemDictionary updates // during compilations. MutexLocker mu(THREAD, Compile_lock); - update_dictionary(THREAD, loaded_class, class_loader); + update_dictionary(THREAD, loaded_class, loader_data); } if (JvmtiExport::should_post_class_load()) { @@ -1469,9 +1473,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // classloader lock held // Parallel classloaders will call find_or_define_instance_class // which will require a token to perform the define class - Symbol* name_h = k->name(); - Dictionary* dictionary = loader_data->dictionary(); - check_constraints(k, class_loader, true, CHECK); + check_constraints(k, loader_data, true, CHECK); // Register class just loaded with class loader (placed in ArrayList) // Note we do this before updating the dictionary, as this can @@ -1495,7 +1497,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // Add to systemDictionary - so other classes can see it. // Grabs and releases SystemDictionary_lock - update_dictionary(THREAD, k, class_loader); + update_dictionary(THREAD, k, loader_data); } // notify jvmti @@ -1528,7 +1530,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handle class_loader, InstanceKlass* k, TRAPS) { - Symbol* name_h = k->name(); // passed in class_name may be null + Symbol* name_h = k->name(); ClassLoaderData* loader_data = class_loader_data(class_loader); Dictionary* dictionary = loader_data->dictionary(); @@ -1725,7 +1727,7 @@ void SystemDictionary::initialize(TRAPS) { // if initiating loader, then ok if InstanceKlass matches existing entry void SystemDictionary::check_constraints(InstanceKlass* k, - Handle class_loader, + ClassLoaderData* loader_data, bool defining, TRAPS) { ResourceMark rm(THREAD); @@ -1733,8 +1735,7 @@ void SystemDictionary::check_constraints(InstanceKlass* k, bool throwException = false; { - Symbol *name = k->name(); - ClassLoaderData *loader_data = class_loader_data(class_loader); + Symbol* name = k->name(); MutexLocker mu(THREAD, SystemDictionary_lock); @@ -1755,13 +1756,13 @@ void SystemDictionary::check_constraints(InstanceKlass* k, } if (throwException == false) { - if (LoaderConstraintTable::check_or_update(k, class_loader, name) == false) { + if (LoaderConstraintTable::check_or_update(k, loader_data, name) == false) { throwException = true; ss.print("loader constraint violation: loader %s", loader_data->loader_name_and_id()); ss.print(" wants to load %s %s.", k->external_kind(), k->external_name()); - Klass *existing_klass = LoaderConstraintTable::find_constrained_klass(name, class_loader); - if (existing_klass != NULL && existing_klass->class_loader() != class_loader()) { + Klass *existing_klass = LoaderConstraintTable::find_constrained_klass(name, loader_data); + if (existing_klass != NULL && existing_klass->class_loader_data() != loader_data) { ss.print(" A different %s with the same name was previously loaded by %s. (%s)", existing_klass->external_kind(), existing_klass->class_loader_data()->loader_name_and_id(), @@ -1784,23 +1785,20 @@ void SystemDictionary::check_constraints(InstanceKlass* k, // have been called. void SystemDictionary::update_dictionary(JavaThread* current, InstanceKlass* k, - Handle class_loader) { + ClassLoaderData* loader_data) { // Compile_lock prevents systemDictionary updates during compilations assert_locked_or_safepoint(Compile_lock); - Symbol* name = k->name(); - ClassLoaderData *loader_data = class_loader_data(class_loader); + Symbol* name = k->name(); - { - MutexLocker mu1(SystemDictionary_lock); + MutexLocker mu1(SystemDictionary_lock); - // Make a new dictionary entry. - Dictionary* dictionary = loader_data->dictionary(); - InstanceKlass* sd_check = dictionary->find_class(current, name); - if (sd_check == NULL) { - dictionary->add_klass(current, name, k); - } - SystemDictionary_lock->notify_all(); + // Make a new dictionary entry. + Dictionary* dictionary = loader_data->dictionary(); + InstanceKlass* sd_check = dictionary->find_class(current, name); + if (sd_check == NULL) { + dictionary->add_klass(current, name, k); } + SystemDictionary_lock->notify_all(); } @@ -1831,7 +1829,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass( klass = Universe::typeArrayKlassObj(t); } else { MutexLocker mu(current, SystemDictionary_lock); - klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader); + klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader_data(class_loader)); } // If element class already loaded, allocate array klass if (klass != NULL) { @@ -1840,7 +1838,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass( } else { MutexLocker mu(current, SystemDictionary_lock); // Non-array classes are easy: simply check the constraint table. - klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader); + klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader_data(class_loader)); } return klass; @@ -1880,8 +1878,8 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name, MutexLocker mu_s(SystemDictionary_lock); InstanceKlass* klass1 = dictionary1->find_class(current, constraint_name); InstanceKlass* klass2 = dictionary2->find_class(current, constraint_name); - bool result = LoaderConstraintTable::add_entry(constraint_name, klass1, class_loader1, - klass2, class_loader2); + bool result = LoaderConstraintTable::add_entry(constraint_name, klass1, loader_data1, + klass2, loader_data2); #if INCLUDE_CDS if (Arguments::is_dumping_archive() && klass_being_linked != NULL && !klass_being_linked->is_shared()) { @@ -2443,10 +2441,6 @@ void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifie } -ClassLoaderData* SystemDictionary::class_loader_data(Handle class_loader) { - return ClassLoaderData::class_loader_data(class_loader()); -} - bool SystemDictionary::is_nonpublic_Object_method(Method* m) { assert(m != NULL, "Unexpected NULL Method*"); return !m->is_public() && m->method_holder() == vmClasses::Object_klass(); diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index e56cf832828..82afbcbf0fb 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -201,10 +201,6 @@ class SystemDictionary : AllStatic { // Returns java system loader static oop java_system_loader(); - // Returns the class loader data to be used when looking up/updating the - // system dictionary. - static ClassLoaderData *class_loader_data(Handle class_loader); - // Returns java platform loader static oop java_platform_loader(); @@ -381,9 +377,9 @@ class SystemDictionary : AllStatic { static Symbol* find_placeholder(Symbol* name, ClassLoaderData* loader_data); // Class loader constraints - static void check_constraints(InstanceKlass* k, Handle loader, + static void check_constraints(InstanceKlass* k, ClassLoaderData* loader, bool defining, TRAPS); - static void update_dictionary(JavaThread* current, InstanceKlass* k, Handle loader); + static void update_dictionary(JavaThread* current, InstanceKlass* k, ClassLoaderData* loader_data); }; #endif // SHARE_CLASSFILE_SYSTEMDICTIONARY_HPP diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 0c3364a8c94..81b442f713b 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -77,7 +77,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { case vmIntrinsics::_isInstance: case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: - case vmIntrinsics::_extentLocalCache: + case vmIntrinsics::_scopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: @@ -127,8 +127,8 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: case vmIntrinsics::_setCurrentThread: - case vmIntrinsics::_extentLocalCache: - case vmIntrinsics::_setExtentLocalCache: + case vmIntrinsics::_scopedValueCache: + case vmIntrinsics::_setScopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: @@ -265,8 +265,8 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { if (!InlineThreadNatives) return true; break; case vmIntrinsics::_setCurrentThread: - case vmIntrinsics::_extentLocalCache: - case vmIntrinsics::_setExtentLocalCache: + case vmIntrinsics::_scopedValueCache: + case vmIntrinsics::_setScopedValueCache: case vmIntrinsics::_floatToRawIntBits: case vmIntrinsics::_intBitsToFloat: case vmIntrinsics::_doubleToRawLongBits: @@ -483,7 +483,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { if (!UseBASE64Intrinsics) return true; break; case vmIntrinsics::_poly1305_processBlocks: - if (!UsePolyIntrinsics) return true; + if (!UsePoly1305Intrinsics) return true; break; case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 70604efe1dc..fb9d9ec9c95 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -270,7 +270,7 @@ class methodHandle; do_intrinsic(_identityHashCode, java_lang_System, identityHashCode_name, object_int_signature, F_SN) \ do_name( identityHashCode_name, "identityHashCode") \ do_intrinsic(_currentTimeMillis, java_lang_System, currentTimeMillis_name, void_long_signature, F_SN) \ - \ + \ do_name( currentTimeMillis_name, "currentTimeMillis") \ do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_SN) \ do_name( nanoTime_name, "nanoTime") \ @@ -286,12 +286,15 @@ class methodHandle; do_intrinsic(_currentThread, java_lang_Thread, currentThread_name, currentThread_signature, F_SN) \ do_name( currentThread_name, "currentThread") \ do_signature(currentThread_signature, "()Ljava/lang/Thread;") \ - do_intrinsic(_extentLocalCache, java_lang_Thread, extentLocalCache_name, extentLocalCache_signature, F_SN) \ - do_name( extentLocalCache_name, "extentLocalCache") \ - do_signature(extentLocalCache_signature, "()[Ljava/lang/Object;") \ - do_intrinsic(_setExtentLocalCache, java_lang_Thread, setExtentLocalCache_name, setExtentLocalCache_signature, F_SN) \ - do_name( setExtentLocalCache_name, "setExtentLocalCache") \ - do_signature(setExtentLocalCache_signature, "([Ljava/lang/Object;)V") \ + do_intrinsic(_scopedValueCache, java_lang_Thread, scopedValueCache_name, scopedValueCache_signature, F_SN) \ + do_name( scopedValueCache_name, "scopedValueCache") \ + do_signature(scopedValueCache_signature, "()[Ljava/lang/Object;") \ + do_intrinsic(_setScopedValueCache, java_lang_Thread, setScopedValueCache_name, setScopedValueCache_signature, F_SN) \ + do_name( setScopedValueCache_name, "setScopedValueCache") \ + do_signature(setScopedValueCache_signature, "([Ljava/lang/Object;)V") \ + do_intrinsic(_findScopedValueBindings, java_lang_Thread, findScopedValueBindings_name, void_object_signature, F_SN) \ + do_name( findScopedValueBindings_name, "findScopedValueBindings") \ + \ do_intrinsic(_setCurrentThread, java_lang_Thread, setCurrentThread_name, thread_void_signature, F_RN) \ do_name( setCurrentThread_name, "setCurrentThread") \ \ @@ -331,6 +334,9 @@ class methodHandle; do_name( onSpinWait_name, "onSpinWait") \ do_alias( onSpinWait_signature, void_method_signature) \ \ + do_intrinsic(_ensureMaterializedForStackWalk, java_lang_Thread, ensureMaterializedForStackWalk_name, object_void_signature, F_SN) \ + do_name( ensureMaterializedForStackWalk_name, "ensureMaterializedForStackWalk") \ + \ do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \ do_name( copyOf_name, "copyOf") \ do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 00ff8e732d2..891292be7b8 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -156,6 +156,8 @@ template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \ template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \ template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \ + template(jdk_incubator_concurrent_ScopedValue, "jdk/incubator/concurrent/ScopedValue") \ + template(jdk_incubator_concurrent_ScopedValue_Carrier, "jdk/incubator/concurrent/ScopedValue$Carrier") \ \ /* Java runtime version access */ \ template(java_lang_VersionProps, "java/lang/VersionProps") \ @@ -396,6 +398,7 @@ template(group_name, "group") \ template(daemon_name, "daemon") \ template(run_method_name, "run") \ + template(runWith_method_name, "runWith") \ template(interrupt_method_name, "interrupt") \ template(exit_method_name, "exit") \ template(remove_method_name, "remove") \ @@ -601,6 +604,7 @@ template(string_array_string_array_void_signature, "([Ljava/lang/String;[Ljava/lang/String;)V") \ template(thread_throwable_void_signature, "(Ljava/lang/Thread;Ljava/lang/Throwable;)V") \ template(thread_void_signature, "(Ljava/lang/Thread;)V") \ + template(runnable_void_signature, "(Ljava/lang/Runnable;)V") \ template(threadgroup_runnable_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V") \ template(threadgroup_string_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V") \ template(void_threadgroup_array_signature, "()[Ljava/lang/ThreadGroup;") \ @@ -741,6 +745,10 @@ do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \ template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \ template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \ + template(serializeSavedPropertiesToByteArray_name, "serializeSavedPropertiesToByteArray") \ + template(encodeThrowable_name, "encodeThrowable") \ + template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \ + template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(classRedefinedCount_name, "classRedefinedCount") \ template(classLoader_name, "classLoader") \ template(componentType_name, "componentType") \ diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index a082dc962e3..c71a5dc3dee 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -792,6 +792,7 @@ void UpcallStub::verify() { void UpcallStub::print_on(outputStream* st) const { RuntimeBlob::print_on(st); print_value_on(st); + Disassembler::decode((RuntimeBlob*)this, st); } void UpcallStub::print_value_on(outputStream* st) const { diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 6da296eb905..8e66deb914e 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -109,7 +109,7 @@ class CodeBlob { // that range. There is a similar range(s) on returns // which we don't detect. int _data_offset; // offset to where data region begins - int _frame_size; // size of stack frame + int _frame_size; // size of stack frame in words (NOT slots. On x64 these are 64bit words) bool _caller_must_gc_arguments; diff --git a/src/hotspot/share/code/codeHeapState.cpp b/src/hotspot/share/code/codeHeapState.cpp index 91cb7c4c53f..fd3b203548d 100644 --- a/src/hotspot/share/code/codeHeapState.cpp +++ b/src/hotspot/share/code/codeHeapState.cpp @@ -258,7 +258,7 @@ static unsigned int used_topSizeBlocks = 0; static struct SizeDistributionElement* SizeDistributionArray = NULL; -static unsigned int latest_compilation_id = 0; +static int latest_compilation_id = 0; static volatile bool initialization_complete = false; const char* CodeHeapState::get_heapName(CodeHeap* heap) { @@ -659,27 +659,27 @@ void CodeHeapState::aggregate(outputStream* out, CodeHeap* heap, size_t granular prepare_SizeDistArray(out, nSizeDistElements, heapName); latest_compilation_id = CompileBroker::get_compilation_id(); - unsigned int highest_compilation_id = 0; - size_t usedSpace = 0; - size_t t1Space = 0; - size_t t2Space = 0; - size_t aliveSpace = 0; - size_t disconnSpace = 0; - size_t notentrSpace = 0; - size_t stubSpace = 0; - size_t freeSpace = 0; - size_t maxFreeSize = 0; - HeapBlock* maxFreeBlock = NULL; - bool insane = false; - - unsigned int n_methods = 0; + int highest_compilation_id = 0; + size_t usedSpace = 0; + size_t t1Space = 0; + size_t t2Space = 0; + size_t aliveSpace = 0; + size_t disconnSpace = 0; + size_t notentrSpace = 0; + size_t stubSpace = 0; + size_t freeSpace = 0; + size_t maxFreeSize = 0; + HeapBlock* maxFreeBlock = NULL; + bool insane = false; + + unsigned int n_methods = 0; for (HeapBlock *h = heap->first_block(); h != NULL && !insane; h = heap->next_block(h)) { unsigned int hb_len = (unsigned int)h->length(); // despite being size_t, length can never overflow an unsigned int. size_t hb_bytelen = ((size_t)hb_len)< age2 ? age1 : age2; + int age1 = StatArray[ix].t1_age; + int age2 = StatArray[ix].t2_age; + int agex = StatArray[ix].tx_age; + int age = age1 > age2 ? age1 : age2; age = age > agex ? age : agex; print_age_single(ast, age); } @@ -2247,9 +2247,7 @@ void CodeHeapState::print_blobType_legend(outputStream* out) { } void CodeHeapState::print_space_legend(outputStream* out) { - unsigned int indicator = 0; - unsigned int age_range = 256; - unsigned int range_beg = latest_compilation_id; + int range_beg = latest_compilation_id; out->cr(); printBox(out, '-', "Space ranges, based on granule occupancy", NULL); out->print_cr(" - 0%% == occupancy"); @@ -2263,12 +2261,12 @@ void CodeHeapState::print_space_legend(outputStream* out) { void CodeHeapState::print_age_legend(outputStream* out) { unsigned int indicator = 0; - unsigned int age_range = 256; - unsigned int range_beg = latest_compilation_id; + int age_range = 256; + int range_beg = latest_compilation_id; out->cr(); printBox(out, '-', "Age ranges, based on compilation id", NULL); while (age_range > 0) { - out->print_cr(" %d - %6d to %6d", indicator, range_beg, latest_compilation_id - latest_compilation_id/age_range); + out->print_cr(" %u - %6d to %6d", indicator, range_beg, latest_compilation_id - latest_compilation_id/age_range); range_beg = latest_compilation_id - latest_compilation_id/age_range; age_range /= 2; indicator += 1; @@ -2293,9 +2291,9 @@ void CodeHeapState::print_space_single(outputStream* out, unsigned short space) out->print("%c", fraction); } -void CodeHeapState::print_age_single(outputStream* out, unsigned int age) { +void CodeHeapState::print_age_single(outputStream* out, int age) { unsigned int indicator = 0; - unsigned int age_range = 256; + int age_range = 256; if (age > 0) { while ((age_range > 0) && (latest_compilation_id-age > latest_compilation_id/age_range)) { age_range /= 2; diff --git a/src/hotspot/share/code/codeHeapState.hpp b/src/hotspot/share/code/codeHeapState.hpp index 1bd41fdda72..6cb536ba958 100644 --- a/src/hotspot/share/code/codeHeapState.hpp +++ b/src/hotspot/share/code/codeHeapState.hpp @@ -88,7 +88,7 @@ class CodeHeapState : public CHeapObj { static void print_blobType_single(outputStream *ast, u2 /* blobType */ type); static void print_count_single(outputStream *ast, unsigned short count); static void print_space_single(outputStream *ast, unsigned short space); - static void print_age_single(outputStream *ast, unsigned int age); + static void print_age_single(outputStream *ast, int age); static void print_line_delim(outputStream* out, bufferedStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); static void print_line_delim(outputStream* out, outputStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); static blobType get_cbType(CodeBlob* cb); @@ -119,9 +119,9 @@ class CodeHeapState : public CHeapObj { class StatElement : public CHeapObj { public: // A note on ages: The compilation_id easily overflows unsigned short in large systems - unsigned int t1_age; // oldest compilation_id of tier1 nMethods. - unsigned int t2_age; // oldest compilation_id of tier2 nMethods. - unsigned int tx_age; // oldest compilation_id of inactive/not entrant nMethods. + int t1_age; // oldest compilation_id of tier1 nMethods. + int t2_age; // oldest compilation_id of tier2 nMethods. + int tx_age; // oldest compilation_id of inactive/not entrant nMethods. unsigned short t1_space; // in units of _segment_size to "prevent" overflow unsigned short t2_space; // in units of _segment_size to "prevent" overflow unsigned short tx_space; // in units of _segment_size to "prevent" overflow diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index 19d51ba111e..6909aa6b2d0 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -777,7 +777,8 @@ void Dependencies::write_dependency_to(xmlStream* xtty, xtty->object("x", arg.metadata_value()); } } else { - char xn[12]; sprintf(xn, "x%d", j); + char xn[12]; + os::snprintf_checked(xn, sizeof(xn), "x%d", j); if (arg.is_oop()) { xtty->object(xn, Handle(thread, arg.oop_value())); } else { diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index e03ab23c4c6..f2304e35c24 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -451,6 +451,42 @@ void nmethod::init_defaults() { #endif } +#ifdef ASSERT +class CheckForOopsClosure : public OopClosure { + bool _found_oop = false; + public: + virtual void do_oop(oop* o) { _found_oop = true; } + virtual void do_oop(narrowOop* o) { _found_oop = true; } + bool found_oop() { return _found_oop; } +}; +class CheckForMetadataClosure : public MetadataClosure { + bool _found_metadata = false; + Metadata* _ignore = nullptr; + public: + CheckForMetadataClosure(Metadata* ignore) : _ignore(ignore) {} + virtual void do_metadata(Metadata* md) { if (md != _ignore) _found_metadata = true; } + bool found_metadata() { return _found_metadata; } +}; + +static void assert_no_oops_or_metadata(nmethod* nm) { + if (nm == nullptr) return; + assert(nm->oop_maps() == nullptr, "expectation"); + + CheckForOopsClosure cfo; + nm->oops_do(&cfo); + assert(!cfo.found_oop(), "no oops allowed"); + + // We allow an exception for the own Method, but require its class to be permanent. + Method* own_method = nm->method(); + CheckForMetadataClosure cfm(/* ignore reference to own Method */ own_method); + nm->metadata_do(&cfm); + assert(!cfm.found_metadata(), "no metadata allowed"); + + assert(own_method->method_holder()->class_loader_data()->is_permanent_class_loader_data(), + "Method's class needs to be permanent"); +} +#endif + nmethod* nmethod::new_native_nmethod(const methodHandle& method, int compile_id, CodeBuffer *code_buffer, @@ -474,14 +510,19 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method, if (exception_handler != -1) { offsets.set_value(CodeOffsets::Exceptions, exception_handler); } - nm = new (native_nmethod_size, CompLevel_none) + + // MH intrinsics are dispatch stubs which are compatible with NonNMethod space. + // IsUnloadingBehaviour::is_unloading needs to handle them separately. + bool allow_NonNMethod_space = method->can_be_allocated_in_NonNMethod_space(); + nm = new (native_nmethod_size, allow_NonNMethod_space) nmethod(method(), compiler_none, native_nmethod_size, compile_id, &offsets, code_buffer, frame_size, basic_lock_owner_sp_offset, basic_lock_sp_offset, oop_maps); - NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); + DEBUG_ONLY( if (allow_NonNMethod_space) assert_no_oops_or_metadata(nm); ) + NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); } if (nm != NULL) { @@ -716,6 +757,14 @@ void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level)); } +void* nmethod::operator new(size_t size, int nmethod_size, bool allow_NonNMethod_space) throw () { + // Try MethodNonProfiled and MethodProfiled. + void* return_value = CodeCache::allocate(nmethod_size, CodeBlobType::MethodNonProfiled); + if (return_value != nullptr || !allow_NonNMethod_space) return return_value; + // Try NonNMethod or give up. + return CodeCache::allocate(nmethod_size, CodeBlobType::NonNMethod); +} + nmethod::nmethod( Method* method, CompilerType type, @@ -1413,14 +1462,14 @@ oop nmethod::oop_at(int index) const { if (index == 0) { return NULL; } - return NativeAccess::oop_load(oop_addr_at(index)); + return NMethodAccess::oop_load(oop_addr_at(index)); } oop nmethod::oop_at_phantom(int index) const { if (index == 0) { return NULL; } - return NativeAccess::oop_load(oop_addr_at(index)); + return NMethodAccess::oop_load(oop_addr_at(index)); } // diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index bd2af1053a0..d9b792e0ef6 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -298,6 +298,10 @@ class nmethod : public CompiledMethod { // helper methods void* operator new(size_t size, int nmethod_size, int comp_level) throw(); + // For method handle intrinsics: Try MethodNonProfiled, MethodProfiled and NonNMethod. + // Attention: Only allow NonNMethod space for special nmethods which don't need to be + // findable by nmethod iterators! In particular, they must not contain oops! + void* operator new(size_t size, int nmethod_size, bool allow_NonNMethod_space) throw(); const char* reloc_string_for(u_char* begin, u_char* end); diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 65b860c9d85..97f3ebd6055 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -36,6 +36,9 @@ #include "utilities/align.hpp" #include "utilities/copy.hpp" +#include +#include + const RelocationHolder RelocationHolder::none; // its type is relocInfo::none @@ -83,7 +86,7 @@ relocInfo* relocInfo::finish_prefix(short* prefix_limit) { return this+1; } // cannot compact, so just update the count and return the limit pointer - (*this) = prefix_relocInfo(plen); // write new datalen + (*this) = prefix_info(plen); // write new datalen assert(data() + datalen() == prefix_limit, "pointers must line up"); return (relocInfo*)prefix_limit; } @@ -235,12 +238,44 @@ Relocation* RelocIterator::reloc() { APPLY_TO_RELOCATIONS(EACH_TYPE); #undef EACH_TYPE assert(t == relocInfo::none, "must be padding"); - return new(_rh) Relocation(t); + _rh = RelocationHolder::none; + return _rh.reloc(); } +// Verify all the destructors are trivial, so we don't need to worry about +// destroying old contents of a RelocationHolder being assigned or destroyed. +#define VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(Reloc) \ + static_assert(std::is_trivially_destructible::value, "must be"); -//////// Methods for flyweight Relocation types +#define VERIFY_TRIVIALLY_DESTRUCTIBLE(name) \ + VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(PASTE_TOKENS(name, _Relocation)); + +APPLY_TO_RELOCATIONS(VERIFY_TRIVIALLY_DESTRUCTIBLE) +VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(Relocation) + +#undef VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX +#undef VERIFY_TRIVIALLY_DESTRUCTIBLE + +// Define all the copy_into functions. These rely on all Relocation types +// being trivially destructible (verified above). So it doesn't matter +// whether the target holder has been previously initialized or not. There's +// no need to consider that distinction and destruct the relocation in an +// already initialized holder. +#define DEFINE_COPY_INTO_AUX(Reloc) \ + void Reloc::copy_into(RelocationHolder& holder) const { \ + copy_into_helper(*this, holder); \ + } +#define DEFINE_COPY_INTO(name) \ + DEFINE_COPY_INTO_AUX(PASTE_TOKENS(name, _Relocation)) + +APPLY_TO_RELOCATIONS(DEFINE_COPY_INTO) +DEFINE_COPY_INTO_AUX(Relocation) + +#undef DEFINE_COPY_INTO_AUX +#undef DEFINE_COPY_INTO + +//////// Methods for RelocationHolder RelocationHolder RelocationHolder::plus(int offset) const { if (offset != 0) { @@ -264,6 +299,8 @@ RelocationHolder RelocationHolder::plus(int offset) const { return (*this); } +//////// Methods for flyweight Relocation types + // some relocations can compute their own values address Relocation::value() { ShouldNotReachHere(); diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp index c0232c79efc..56a10731dcd 100644 --- a/src/hotspot/share/code/relocInfo.hpp +++ b/src/hotspot/share/code/relocInfo.hpp @@ -28,8 +28,10 @@ #include "memory/allocation.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/osInfo.hpp" -#include "utilities/macros.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +#include class nmethod; class CodeBlob; @@ -366,7 +368,9 @@ class relocInfo { // - to pad out the relocInfo array to the required oop alignment // - to disable old relocation information which is no longer applicable - inline friend relocInfo filler_relocInfo(); + static relocInfo filler_info() { + return relocInfo(relocInfo::none, relocInfo::offset_limit() - relocInfo::offset_unit); + } // Every non-prefix relocation may be preceded by at most one prefix, // which supplies 1 or more halfwords of associated data. Conventionally, @@ -376,7 +380,10 @@ class relocInfo { // "immediate" in the prefix header word itself. This optimization // is invisible outside this module.) - inline friend relocInfo prefix_relocInfo(int datalen); + static relocInfo prefix_info(int datalen = 0) { + assert(relocInfo::fits_into_immediate(datalen), "datalen in limits"); + return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen); + } private: // an immediate relocInfo optimizes a prefix with one 10-bit unsigned value @@ -454,41 +461,75 @@ class name##_Relocation; APPLY_TO_RELOCATIONS(FORWARD_DECLARE_EACH_CLASS) #undef FORWARD_DECLARE_EACH_CLASS - - -inline relocInfo filler_relocInfo() { - return relocInfo(relocInfo::none, relocInfo::offset_limit() - relocInfo::offset_unit); -} - -inline relocInfo prefix_relocInfo(int datalen = 0) { - assert(relocInfo::fits_into_immediate(datalen), "datalen in limits"); - return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen); -} - - // Holder for flyweight relocation objects. // Although the flyweight subclasses are of varying sizes, // the holder is "one size fits all". class RelocationHolder { friend class Relocation; - friend class CodeSection; private: - // this preallocated memory must accommodate all subclasses of Relocation - // (this number is assertion-checked in Relocation::operator new) - enum { _relocbuf_size = 5 }; - void* _relocbuf[ _relocbuf_size ]; + // A Relocation is "held" by placement constructing a Relocation into + // _relocbuf. Hence, _relocbuf must accomodate all subclasses of + // Relocation. We also need the Relocation base class to be at the same + // address as the start of the object, e.g. at the address of _relocbuf. + // Both of these requirements are checked (see emplace_relocation). + // The placement of the base class subobject isn't guaranteed by C++, since + // these aren't standard layout classes, but all supported implementations + // provide that behavior. If that changes, we can instead add a Relocation* + // _reloc member to capture the result of the placement new, and use that to + // access the base subobject. + static const size_t _relocbuf_size = 5 * sizeof(void*); + alignas(void*) char _relocbuf[_relocbuf_size]; + + template + void emplace_relocation(const Args&... args) { + static_assert(std::is_base_of::value, "not Relocation"); + static_assert(sizeof(Reloc) <= sizeof(_relocbuf), "_relocbuf too small"); + Relocation* reloc = ::new (_relocbuf) Reloc(args...); + // Verify the base class subobject of the object constructed into + // _relocbuf is at the same address as the derived object. + assert(static_cast(reloc) == _relocbuf, "invariant"); + } + + // Support for Relocation::copy_into. + // reloc should be a most derived object. + template + void copy_into_impl(const Reloc& reloc) { + emplace_relocation(reloc); + } + + // Tag for selecting the constructor below and carrying the type of the + // relocation object the new holder will (initially) contain. + template struct Construct {}; + + // Constructor used by construct(). Constructs a new holder containing a + // relocation of type Reloc that is constructed using the provided args. + template + RelocationHolder(Construct, const Args&... args) { + emplace_relocation(args...); + } public: - Relocation* reloc() const { return (Relocation*) &_relocbuf[0]; } + Relocation* reloc() const { return (Relocation*)_relocbuf; } inline relocInfo::relocType type() const; // Add a constant offset to a relocation. Helper for class Address. RelocationHolder plus(int offset) const; - inline RelocationHolder(); // initializes type to none + // Return a holder containing a relocation of type Reloc, constructed using args. + template + static RelocationHolder construct(const Args&... args) { + return RelocationHolder(Construct(), args...); + } + + RelocationHolder(); // Initializes type to none. + + // Depends on the destructor for all relocation types being trivial + // (verified in .cpp file). + ~RelocationHolder() = default; - inline RelocationHolder(Relocation* r); // make a copy + RelocationHolder(const RelocationHolder& from); + RelocationHolder& operator=(const RelocationHolder& from); static const RelocationHolder none; }; @@ -636,7 +677,6 @@ class RelocIterator : public StackObj { // So, the RelocIterator unpacks relocInfos into Relocations. class Relocation { - friend class RelocationHolder; friend class RelocIterator; private: @@ -658,19 +698,18 @@ class Relocation { assert(_binding != NULL, "must now be bound"); } - Relocation(relocInfo::relocType rtype) : _binding(NULL), _rtype(rtype) { } + explicit Relocation(relocInfo::relocType rtype) : _binding(NULL), _rtype(rtype) { } - static RelocationHolder newHolder() { - return RelocationHolder(); + // Helper for copy_into functions for derived classes. + // Forwards operation to RelocationHolder::copy_into_impl so that + // RelocationHolder only needs to befriend this class, rather than all + // derived classes that implement copy_into. + template + static void copy_into_helper(const Reloc& reloc, RelocationHolder& holder) { + holder.copy_into_impl(reloc); } public: - void* operator new(size_t size, const RelocationHolder& holder) throw() { - assert(size <= sizeof(holder._relocbuf), "Make _relocbuf bigger!"); - assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree"); - return holder.reloc(); - } - // make a generic relocation for a given type (if possible) static RelocationHolder spec_simple(relocInfo::relocType rtype); @@ -793,8 +832,20 @@ class Relocation { int format() const { return binding()->format(); } public: + // Make a filler relocation. + Relocation() : Relocation(relocInfo::none) {} + + // Intentionally public non-virtual destructor, even though polymorphic. We + // never heap allocate a Relocation, so never delete through a base pointer. + // RelocationHolder depends on the destructor for all relocation types being + // trivial, so this must not be virtual (and hence non-trivial). + ~Relocation() = default; + relocInfo::relocType type() const { return _rtype; } + // Copy this relocation into holder. + virtual void copy_into(RelocationHolder& holder) const; + // is it a call instruction? virtual bool is_call() { return false; } @@ -818,17 +869,20 @@ class Relocation { // certain inlines must be deferred until class Relocation is defined: -inline RelocationHolder::RelocationHolder() { - // initialize the vtbl, just to keep things type-safe - new(*this) Relocation(relocInfo::none); -} +inline RelocationHolder::RelocationHolder() : + RelocationHolder(Construct()) +{} +inline RelocationHolder::RelocationHolder(const RelocationHolder& from) { + from.reloc()->copy_into(*this); +} -inline RelocationHolder::RelocationHolder(Relocation* r) { - // wordwise copy from r (ok if it copies garbage after r) - for (int i = 0; i < _relocbuf_size; i++) { - _relocbuf[i] = ((void**)r)[i]; - } +inline RelocationHolder& RelocationHolder::operator=(const RelocationHolder& from) { + // All Relocation types are trivially destructible (verified in .cpp file), + // so we don't need to destruct our old value before copying over it. + // If not for that we would need to decide what to do about self-assignment. + from.reloc()->copy_into(*this); + return *this; } relocInfo::relocType RelocationHolder::type() const { @@ -843,12 +897,12 @@ class DataRelocation : public Relocation { public: DataRelocation(relocInfo::relocType type) : Relocation(type) {} - bool is_data() { return true; } + bool is_data() override { return true; } // both target and offset must be computed somehow from relocation data virtual int offset() { return 0; } - address value() = 0; - void set_value(address x) { set_value(x, offset()); } + address value() override = 0; + void set_value(address x) override { set_value(x, offset()); } void set_value(address x, intptr_t o) { if (addr_in_const()) const_set_data_value(x); @@ -876,29 +930,29 @@ class DataRelocation : public Relocation { }; class post_call_nop_Relocation : public Relocation { - friend class RelocIterator; + friend class RelocationHolder; public: post_call_nop_Relocation() : Relocation(relocInfo::post_call_nop_type) { } static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) post_call_nop_Relocation(); - return rh; + return RelocationHolder::construct(); } + + void copy_into(RelocationHolder& holder) const override; }; class entry_guard_Relocation : public Relocation { - friend class RelocIterator; + friend class RelocationHolder; public: entry_guard_Relocation() : Relocation(relocInfo::entry_guard_type) { } static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) entry_guard_Relocation(); - return rh; + return RelocationHolder::construct(); } + + void copy_into(RelocationHolder& holder) const override; }; // A CallRelocation always points at a call instruction. @@ -907,14 +961,14 @@ class CallRelocation : public Relocation { public: CallRelocation(relocInfo::relocType type) : Relocation(type) { } - bool is_call() { return true; } + bool is_call() override { return true; } address destination() { return pd_call_destination(); } void set_destination(address x); // pd_set_call_destination - void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); - address value() { return destination(); } - void set_value(address x) { set_destination(x); } + void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) override; + address value() override { return destination(); } + void set_value(address x) override { set_destination(x); } }; class oop_Relocation : public DataRelocation { @@ -923,9 +977,7 @@ class oop_Relocation : public DataRelocation { // an oop in the CodeBlob's oop pool static RelocationHolder spec(int oop_index, int offset = 0) { assert(oop_index > 0, "must be a pool-resident oop"); - RelocationHolder rh = newHolder(); - new(rh) oop_Relocation(oop_index, offset); - return rh; + return RelocationHolder::construct(oop_index, offset); } // an oop in the instruction stream static RelocationHolder spec_for_immediate() { @@ -935,11 +987,11 @@ class oop_Relocation : public DataRelocation { "Must return true so we will search for oops as roots etc. in the code."); const int oop_index = 0; const int offset = 0; // if you want an offset, use the oop pool - RelocationHolder rh = newHolder(); - new(rh) oop_Relocation(oop_index, offset); - return rh; + return RelocationHolder::construct(oop_index, offset); } + void copy_into(RelocationHolder& holder) const override; + private: jint _oop_index; // if > 0, index into CodeBlob::oop_at jint _offset; // byte offset to apply to the oop itself @@ -947,22 +999,22 @@ class oop_Relocation : public DataRelocation { oop_Relocation(int oop_index, int offset) : DataRelocation(relocInfo::oop_type), _oop_index(oop_index), _offset(offset) { } - friend class RelocIterator; + friend class RelocationHolder; oop_Relocation() : DataRelocation(relocInfo::oop_type) {} public: int oop_index() { return _oop_index; } - int offset() { return _offset; } + int offset() override { return _offset; } // data is packed in "2_ints" format: [i o] or [Ii Oo] - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; void fix_oop_relocation(); // reasserts oop value void verify_oop_relocation(); - address value() { return cast_from_oop

    (*oop_addr()); } + address value() override { return cast_from_oop
    (*oop_addr()); } bool oop_is_immediate() { return oop_index() == 0; } @@ -980,19 +1032,17 @@ class metadata_Relocation : public DataRelocation { // an metadata in the CodeBlob's metadata pool static RelocationHolder spec(int metadata_index, int offset = 0) { assert(metadata_index > 0, "must be a pool-resident metadata"); - RelocationHolder rh = newHolder(); - new(rh) metadata_Relocation(metadata_index, offset); - return rh; + return RelocationHolder::construct(metadata_index, offset); } // an metadata in the instruction stream static RelocationHolder spec_for_immediate() { const int metadata_index = 0; const int offset = 0; // if you want an offset, use the metadata pool - RelocationHolder rh = newHolder(); - new(rh) metadata_Relocation(metadata_index, offset); - return rh; + return RelocationHolder::construct(metadata_index, offset); } + void copy_into(RelocationHolder& holder) const override; + private: jint _metadata_index; // if > 0, index into nmethod::metadata_at jint _offset; // byte offset to apply to the metadata itself @@ -1000,7 +1050,7 @@ class metadata_Relocation : public DataRelocation { metadata_Relocation(int metadata_index, int offset) : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index), _offset(offset) { } - friend class RelocIterator; + friend class RelocationHolder; metadata_Relocation() : DataRelocation(relocInfo::metadata_type) { } // Fixes a Metadata pointer in the code. Most platforms embeds the @@ -1010,15 +1060,15 @@ class metadata_Relocation : public DataRelocation { public: int metadata_index() { return _metadata_index; } - int offset() { return _offset; } + int offset() override { return _offset; } // data is packed in "2_ints" format: [i o] or [Ii Oo] - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; void fix_metadata_relocation(); // reasserts metadata value - address value() { return (address) *metadata_addr(); } + address value() override { return (address) *metadata_addr(); } bool metadata_is_immediate() { return metadata_index() == 0; } @@ -1035,11 +1085,11 @@ class virtual_call_Relocation : public CallRelocation { // The oop_limit helps find the last associated set-oop. // (See comments at the top of this file.) static RelocationHolder spec(address cached_value, jint method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) virtual_call_Relocation(cached_value, method_index); - return rh; + return RelocationHolder::construct(cached_value, method_index); } + void copy_into(RelocationHolder& holder) const override; + private: address _cached_value; // location of set-value instruction jint _method_index; // resolved method for a Java call @@ -1051,7 +1101,7 @@ class virtual_call_Relocation : public CallRelocation { assert(cached_value != NULL, "first oop address must be specified"); } - friend class RelocIterator; + friend class RelocationHolder; virtual_call_Relocation() : CallRelocation(relocInfo::virtual_call_type) { } public: @@ -1064,21 +1114,21 @@ class virtual_call_Relocation : public CallRelocation { // oop_limit is set to 0 if the limit falls somewhere within the call. // When unpacking, a zero oop_limit is taken to refer to the end of the call. // (This has the effect of bringing in the call's delay slot on SPARC.) - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; - bool clear_inline_cache(); + bool clear_inline_cache() override; }; class opt_virtual_call_Relocation : public CallRelocation { public: static RelocationHolder spec(int method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) opt_virtual_call_Relocation(method_index); - return rh; + return RelocationHolder::construct(method_index); } + void copy_into(RelocationHolder& holder) const override; + private: jint _method_index; // resolved method for a Java call @@ -1086,17 +1136,17 @@ class opt_virtual_call_Relocation : public CallRelocation { : CallRelocation(relocInfo::opt_virtual_call_type), _method_index(method_index) { } - friend class RelocIterator; + friend class RelocationHolder; opt_virtual_call_Relocation() : CallRelocation(relocInfo::opt_virtual_call_type) {} public: int method_index() { return _method_index; } Method* method_value(); - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; - bool clear_inline_cache(); + bool clear_inline_cache() override; // find the matching static_stub address static_stub(); @@ -1106,11 +1156,11 @@ class opt_virtual_call_Relocation : public CallRelocation { class static_call_Relocation : public CallRelocation { public: static RelocationHolder spec(int method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) static_call_Relocation(method_index); - return rh; + return RelocationHolder::construct(method_index); } + void copy_into(RelocationHolder& holder) const override; + private: jint _method_index; // resolved method for a Java call @@ -1118,17 +1168,17 @@ class static_call_Relocation : public CallRelocation { : CallRelocation(relocInfo::static_call_type), _method_index(method_index) { } - friend class RelocIterator; + friend class RelocationHolder; static_call_Relocation() : CallRelocation(relocInfo::static_call_type) {} public: int method_index() { return _method_index; } Method* method_value(); - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; - bool clear_inline_cache(); + bool clear_inline_cache() override; // find the matching static_stub address static_stub(); @@ -1137,11 +1187,11 @@ class static_call_Relocation : public CallRelocation { class static_stub_Relocation : public Relocation { public: static RelocationHolder spec(address static_call) { - RelocationHolder rh = newHolder(); - new(rh) static_stub_Relocation(static_call); - return rh; + return RelocationHolder::construct(static_call); } + void copy_into(RelocationHolder& holder) const override; + private: address _static_call; // location of corresponding static_call @@ -1149,46 +1199,44 @@ class static_stub_Relocation : public Relocation { : Relocation(relocInfo::static_stub_type), _static_call(static_call) { } - friend class RelocIterator; + friend class RelocationHolder; static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { } public: - bool clear_inline_cache(); + bool clear_inline_cache() override; address static_call() { return _static_call; } // data is packed as a scaled offset in "1_int" format: [c] or [Cc] - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; }; class runtime_call_Relocation : public CallRelocation { public: static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) runtime_call_Relocation(); - return rh; + return RelocationHolder::construct(); } + void copy_into(RelocationHolder& holder) const override; + private: - friend class RelocIterator; + friend class RelocationHolder; runtime_call_Relocation() : CallRelocation(relocInfo::runtime_call_type) { } - - public: }; class runtime_call_w_cp_Relocation : public CallRelocation { public: static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) runtime_call_w_cp_Relocation(); - return rh; + return RelocationHolder::construct(); } + void copy_into(RelocationHolder& holder) const override; + private: - friend class RelocIterator; + friend class RelocationHolder; runtime_call_w_cp_Relocation() : CallRelocation(relocInfo::runtime_call_w_cp_type), _offset(-4) /* <0 = invalid */ { } @@ -1205,8 +1253,8 @@ class runtime_call_w_cp_Relocation : public CallRelocation { public: void set_constant_pool_offset(int offset) { _offset = offset; } int get_constant_pool_offset() { return _offset; } - void pack_data_to(CodeSection * dest); - void unpack_data(); + void pack_data_to(CodeSection * dest) override; + void unpack_data() override; }; // Trampoline Relocations. @@ -1218,10 +1266,11 @@ class runtime_call_w_cp_Relocation : public CallRelocation { class trampoline_stub_Relocation : public Relocation { public: static RelocationHolder spec(address static_call) { - RelocationHolder rh = newHolder(); - return (new (rh) trampoline_stub_Relocation(static_call)); + return RelocationHolder::construct(static_call); } + void copy_into(RelocationHolder& holder) const override; + private: address _owner; // Address of the NativeCall that owns the trampoline. @@ -1229,7 +1278,7 @@ class trampoline_stub_Relocation : public Relocation { : Relocation(relocInfo::trampoline_stub_type), _owner(owner) { } - friend class RelocIterator; + friend class RelocationHolder; trampoline_stub_Relocation() : Relocation(relocInfo::trampoline_stub_type) { } public: @@ -1237,8 +1286,8 @@ class trampoline_stub_Relocation : public Relocation { // Return the address of the NativeCall that owns the trampoline. address owner() { return _owner; } - void pack_data_to(CodeSection * dest); - void unpack_data(); + void pack_data_to(CodeSection * dest) override; + void unpack_data() override; // Find the trampoline stub for a call. static address get_trampoline_for(address call, nmethod* code); @@ -1248,19 +1297,17 @@ class external_word_Relocation : public DataRelocation { public: static RelocationHolder spec(address target) { assert(target != NULL, "must not be null"); - RelocationHolder rh = newHolder(); - new(rh) external_word_Relocation(target); - return rh; + return RelocationHolder::construct(target); } // Use this one where all 32/64 bits of the target live in the code stream. // The target must be an intptr_t, and must be absolute (not relative). static RelocationHolder spec_for_immediate() { - RelocationHolder rh = newHolder(); - new(rh) external_word_Relocation(NULL); - return rh; + return RelocationHolder::construct(nullptr); } + void copy_into(RelocationHolder& holder) const override; + // Some address looking values aren't safe to treat as relocations // and should just be treated as constants. static bool can_be_relocated(address target) { @@ -1274,7 +1321,7 @@ class external_word_Relocation : public DataRelocation { external_word_Relocation(address target) : DataRelocation(relocInfo::external_word_type), _target(target) { } - friend class RelocIterator; + friend class RelocationHolder; external_word_Relocation() : DataRelocation(relocInfo::external_word_type) { } public: @@ -1283,12 +1330,12 @@ class external_word_Relocation : public DataRelocation { // to short indexes, if they are pre-registered by the stub mechanism. // If the "a" value is 0 (i.e., _target is NULL), the address is stored // in the code stream. See external_word_Relocation::target(). - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; - void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); + void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) override; address target(); // if _target==NULL, fetch addr from code stream - address value() { return target(); } + address value() override { return target(); } }; class internal_word_Relocation : public DataRelocation { @@ -1296,18 +1343,16 @@ class internal_word_Relocation : public DataRelocation { public: static RelocationHolder spec(address target) { assert(target != NULL, "must not be null"); - RelocationHolder rh = newHolder(); - new(rh) internal_word_Relocation(target); - return rh; + return RelocationHolder::construct(target); } // use this one where all the bits of the target can fit in the code stream: static RelocationHolder spec_for_immediate() { - RelocationHolder rh = newHolder(); - new(rh) internal_word_Relocation(NULL); - return rh; + return RelocationHolder::construct(nullptr); } + void copy_into(RelocationHolder& holder) const override; + // default section -1 means self-relative internal_word_Relocation(address target, int section = -1, relocInfo::relocType type = relocInfo::internal_word_type) @@ -1317,7 +1362,7 @@ class internal_word_Relocation : public DataRelocation { address _target; // address in CodeBlob int _section; // section providing base address, if any - friend class RelocIterator; + friend class RelocationHolder; internal_word_Relocation(relocInfo::relocType type = relocInfo::internal_word_type) : DataRelocation(type) { } @@ -1329,23 +1374,23 @@ class internal_word_Relocation : public DataRelocation { // If the "o" value is 0 (i.e., _target is NULL), the offset is stored // in the code stream. See internal_word_Relocation::target(). // If _section is not -1, it is appended to the low bits of the offset. - void pack_data_to(CodeSection* dest); - void unpack_data(); + void pack_data_to(CodeSection* dest) override; + void unpack_data() override; - void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); + void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) override; address target(); // if _target==NULL, fetch addr from code stream int section() { return _section; } - address value() { return target(); } + address value() override { return target(); } }; class section_word_Relocation : public internal_word_Relocation { public: static RelocationHolder spec(address target, int section) { - RelocationHolder rh = newHolder(); - new(rh) section_word_Relocation(target, section); - return rh; + return RelocationHolder::construct(target, section); } + void copy_into(RelocationHolder& holder) const override; + section_word_Relocation(address target, int section) : internal_word_Relocation(target, section, relocInfo::section_word_type) { assert(target != NULL, "must not be null"); @@ -1353,38 +1398,45 @@ class section_word_Relocation : public internal_word_Relocation { } //void pack_data_to -- inherited - void unpack_data(); + void unpack_data() override; private: - friend class RelocIterator; + friend class RelocationHolder; section_word_Relocation() : internal_word_Relocation(relocInfo::section_word_type) { } }; class poll_Relocation : public Relocation { - bool is_data() { return true; } - void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); + bool is_data() override { return true; } + void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) override; public: poll_Relocation(relocInfo::relocType type = relocInfo::poll_type) : Relocation(type) { } + + void copy_into(RelocationHolder& holder) const override; }; class poll_return_Relocation : public poll_Relocation { public: poll_return_Relocation() : poll_Relocation(relocInfo::relocInfo::poll_return_type) { } + + void copy_into(RelocationHolder& holder) const override; }; // We know all the xxx_Relocation classes, so now we can define these: -#define EACH_CASE(name) \ -inline name##_Relocation* RelocIterator::name##_reloc() { \ - assert(type() == relocInfo::name##_type, "type must agree"); \ - /* The purpose of the placed "new" is to re-use the same */ \ - /* stack storage for each new iteration. */ \ - name##_Relocation* r = new(_rh) name##_Relocation(); \ - r->set_binding(this); \ - r->name##_Relocation::unpack_data(); \ - return r; \ +#define EACH_CASE_AUX(Accessor, Reloc) \ +inline Reloc* RelocIterator::Accessor() { \ + static const RelocationHolder proto = RelocationHolder::construct(); \ + assert(type() == proto.type(), "type must agree"); \ + _rh = proto; \ + Reloc* r = static_cast(_rh.reloc()); \ + r->set_binding(this); \ + r->Reloc::unpack_data(); \ + return r; \ } +#define EACH_CASE(name) \ + EACH_CASE_AUX(PASTE_TOKENS(name, _reloc), PASTE_TOKENS(name, _Relocation)) APPLY_TO_RELOCATIONS(EACH_CASE); +#undef EACH_CASE_AUX #undef EACH_CASE inline RelocIterator::RelocIterator(CompiledMethod* nm, address begin, address limit) { diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 0f6cde1c0f4..94cbb08f048 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -932,7 +932,7 @@ void CompileBroker::init_compiler_threads() { // for JVMCI compiler which can create further ones on demand. JVMCI_ONLY(if (!UseJVMCICompiler || !UseDynamicNumberOfCompilerThreads || i == 0) {) // Create a name for our thread. - sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i); Handle thread_oop = create_thread_oop(name_buffer, CHECK); thread_handle = JNIHandles::make_global(thread_oop); JVMCI_ONLY(}) @@ -954,7 +954,7 @@ void CompileBroker::init_compiler_threads() { for (int i = 0; i < _c1_count; i++) { // Create a name for our thread. - sprintf(name_buffer, "C1 CompilerThread%d", i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "C1 CompilerThread%d", i); Handle thread_oop = create_thread_oop(name_buffer, CHECK); jobject thread_handle = JNIHandles::make_global(thread_oop); _compiler1_objects[i] = thread_handle; @@ -1018,7 +1018,7 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) { // transitions if we bind them to new JavaThreads. if (!THREAD->can_call_java()) break; char name_buffer[256]; - sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i); Handle thread_oop; { // We have to give up the lock temporarily for the Java calls. @@ -1566,7 +1566,7 @@ int CompileBroker::assign_compile_id(const methodHandle& method, int osr_bci) { // CompileBroker::assign_compile_id_unlocked // // Public wrapper for assign_compile_id that acquires the needed locks -uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci) { +int CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci) { MutexLocker locker(thread, MethodCompileQueue_lock); return assign_compile_id(method, osr_bci); } @@ -2109,7 +2109,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { } // Common flags. - uint compile_id = task->compile_id(); + int compile_id = task->compile_id(); int osr_bci = task->osr_bci(); bool is_osr = (osr_bci != standard_entry_bci); bool should_log = (thread->log() != NULL); @@ -2432,7 +2432,7 @@ void CompileBroker::update_compile_perf_data(CompilerThread* thread, const metho void CompileBroker::collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task) { bool success = task->is_success(); methodHandle method (thread, task->method()); - uint compile_id = task->compile_id(); + int compile_id = task->compile_id(); bool is_osr = (task->osr_bci() != standard_entry_bci); const int comp_level = task->comp_level(); CompilerCounters* counters = thread->counters(); @@ -2600,7 +2600,7 @@ void CompileBroker::print_times(bool per_compiler, bool aggregate) { char tier_name[256]; for (int tier = CompLevel_simple; tier <= CompilationPolicy::highest_compile_level(); tier++) { CompilerStatistics* stats = &_stats_per_level[tier-1]; - sprintf(tier_name, "Tier%d", tier); + os::snprintf_checked(tier_name, sizeof(tier_name), "Tier%d", tier); print_times(tier_name, stats); } } diff --git a/src/hotspot/share/compiler/compileBroker.hpp b/src/hotspot/share/compiler/compileBroker.hpp index 86cc3803681..417f27c1718 100644 --- a/src/hotspot/share/compiler/compileBroker.hpp +++ b/src/hotspot/share/compiler/compileBroker.hpp @@ -312,10 +312,10 @@ class CompileBroker: AllStatic { TRAPS); // Acquire any needed locks and assign a compile id - static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); + static int assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); static void compiler_thread_loop(); - static uint get_compilation_id() { return _compilation_id; } + static int get_compilation_id() { return _compilation_id; } // Set _should_block. // Call this from the VM, with Threads_lock held and a safepoint requested. diff --git a/src/hotspot/share/compiler/compileTask.hpp b/src/hotspot/share/compiler/compileTask.hpp index 4d35976a42d..bbe1387ffe6 100644 --- a/src/hotspot/share/compiler/compileTask.hpp +++ b/src/hotspot/share/compiler/compileTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -76,7 +76,7 @@ class CompileTask : public CHeapObj { private: static CompileTask* _task_free_list; Monitor* _lock; - uint _compile_id; + int _compile_id; Method* _method; jobject _method_holder; int _osr_bci; diff --git a/src/hotspot/share/compiler/directivesParser.cpp b/src/hotspot/share/compiler/directivesParser.cpp index e48ac58b31c..edb7a3af918 100644 --- a/src/hotspot/share/compiler/directivesParser.cpp +++ b/src/hotspot/share/compiler/directivesParser.cpp @@ -96,10 +96,9 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* // read contents into resource array char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1); ssize_t num_read = ::read(file_handle, (char*) buffer, st.st_size); + ::close(file_handle); if (num_read >= 0) { buffer[num_read] = '\0'; - // close file - ::close(file_handle); return parse_string(buffer, stream) > 0; } } diff --git a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp index ba8fa8a5ea3..f4a03e50ea3 100644 --- a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp +++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -153,7 +153,7 @@ void G1BarrierSetC1::post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Opr new_v LIR_Opr xor_res = gen->new_pointer_register(); LIR_Opr xor_shift_res = gen->new_pointer_register(); - if (TwoOperandLIRForm) { + if (two_operand_lir_form) { __ move(addr, xor_res); __ logical_xor(xor_res, new_val, xor_res); __ move(xor_res, xor_shift_res); diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 753644519c5..d08acc137c9 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -1009,7 +1009,7 @@ void G1BarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) co if (if_ctrl != load_ctrl) { // Skip possible CProj->NeverBranch in infinite loops if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) - && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { + && if_ctrl->in(0)->is_NeverBranch()) { if_ctrl = if_ctrl->in(0)->in(0); } } diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.hpp b/src/hotspot/share/gc/g1/g1AllocRegion.hpp index 4abf3530533..a609472a5c9 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.hpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.hpp @@ -88,6 +88,10 @@ class G1AllocRegion : public CHeapObj { // to allocate a new region even if the max has been reached. HeapWord* new_alloc_region_and_allocate(size_t word_size, bool force); + // Perform an allocation out of a new allocation region, retiring the current one. + inline HeapWord* attempt_allocation_using_new_region(size_t min_word_size, + size_t desired_word_size, + size_t* actual_word_size); protected: // The memory node index this allocation region belongs to. uint _node_index; @@ -172,11 +176,6 @@ class G1AllocRegion : public CHeapObj { size_t desired_word_size, size_t* actual_word_size); - // Perform an allocation out of a new allocation region, retiring the current one. - inline HeapWord* attempt_allocation_using_new_region(size_t min_word_size, - size_t desired_word_size, - size_t* actual_word_size); - // Should be called to allocate a new region even if the max of this // type of regions has been reached. Should only be called if other // allocation attempts have failed and we are not holding a valid diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 4de83eb6d4c..6eab853381b 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -254,8 +254,8 @@ HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size, // the memory may have been used up as the threads waited to acquire the lock. if (!survivor_is_full()) { result = survivor_gc_alloc_region(node_index)->attempt_allocation_locked(min_word_size, - desired_word_size, - actual_word_size); + desired_word_size, + actual_word_size); if (result == NULL) { set_survivor_full(); } diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index bc97de7fc15..9dd5fcdebe6 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -117,10 +117,6 @@ class G1Allocator : public CHeapObj { size_t desired_word_size, size_t* actual_word_size); - // Attempt allocation, retiring the current region and allocating a new one. It is - // assumed that attempt_allocation() has been tried and failed already first. - inline HeapWord* attempt_allocation_using_new_region(size_t word_size); - // This is to be called when holding an appropriate lock. It first tries in the // current allocation region, and then attempts an allocation using a new region. inline HeapWord* attempt_allocation_locked(size_t word_size); diff --git a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp index 0237e002140..aa10347ad4e 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp @@ -62,16 +62,6 @@ inline HeapWord* G1Allocator::attempt_allocation(size_t min_word_size, return mutator_alloc_region(node_index)->attempt_allocation(min_word_size, desired_word_size, actual_word_size); } -inline HeapWord* G1Allocator::attempt_allocation_using_new_region(size_t word_size) { - uint node_index = current_node_index(); - size_t temp; - HeapWord* result = mutator_alloc_region(node_index)->attempt_allocation_using_new_region(word_size, word_size, &temp); - assert(result != NULL || mutator_alloc_region(node_index)->get() == NULL, - "Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, - p2i(mutator_alloc_region(node_index)->get())); - return result; -} - inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) { uint node_index = current_node_index(); HeapWord* result = mutator_alloc_region(node_index)->attempt_allocation_locked(word_size); diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.cpp b/src/hotspot/share/gc/g1/g1BarrierSet.cpp index 0e441ba0868..5032cb99bf4 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp @@ -107,22 +107,28 @@ void G1BarrierSet::invalidate(MemRegion mr) { } volatile CardValue* byte = _card_table->byte_for(mr.start()); CardValue* last_byte = _card_table->byte_for(mr.last()); - // skip initial young cards - for (; byte <= last_byte && *byte == G1CardTable::g1_young_card_val(); byte++); - if (byte <= last_byte) { - OrderAccess::storeload(); - // Enqueue if necessary. - Thread* thr = Thread::current(); - G1DirtyCardQueueSet& qset = G1BarrierSet::dirty_card_queue_set(); - G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thr); - for (; byte <= last_byte; byte++) { - CardValue bv = *byte; - if ((bv != G1CardTable::g1_young_card_val()) && - (bv != G1CardTable::dirty_card_val())) { - *byte = G1CardTable::dirty_card_val(); - qset.enqueue(queue, byte); - } + // skip young gen cards + if (*byte == G1CardTable::g1_young_card_val()) { + // MemRegion should not span multiple regions for the young gen. + DEBUG_ONLY(HeapRegion* containing_hr = G1CollectedHeap::heap()->heap_region_containing(mr.start());) + assert(containing_hr->is_young(), "it should be young"); + assert(containing_hr->is_in(mr.start()), "it should contain start"); + assert(containing_hr->is_in(mr.last()), "it should also contain last"); + return; + } + + OrderAccess::storeload(); + // Enqueue if necessary. + Thread* thr = Thread::current(); + G1DirtyCardQueueSet& qset = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thr); + for (; byte <= last_byte; byte++) { + CardValue bv = *byte; + assert(bv != G1CardTable::g1_young_card_val(), "Invalid card"); + if (bv != G1CardTable::dirty_card_val()) { + *byte = G1CardTable::dirty_card_val(); + qset.enqueue(queue, byte); } } } diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index a90715a51e4..32979545493 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -49,12 +49,6 @@ G1BlockOffsetTable::G1BlockOffsetTable(MemRegion heap, G1RegionToSpaceMapper* st p2i(bot_reserved.start()), bot_reserved.byte_size(), p2i(bot_reserved.end())); } -bool G1BlockOffsetTable::is_card_boundary(HeapWord* p) const { - assert(p >= _reserved.start(), "just checking"); - size_t delta = pointer_delta(p, _reserved.start()); - return (delta & right_n_bits((int)BOTConstants::log_card_size_in_words())) == (size_t)NoBits; -} - #ifdef ASSERT void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { assert((index) < (_reserved.word_size() >> BOTConstants::log_card_size_in_words()), diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index fc9423a1160..966cf472a21 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -71,8 +71,6 @@ class G1BlockOffsetTable: public CHeapObj { inline void set_offset_array(size_t left, size_t right, u_char offset); - bool is_card_boundary(HeapWord* p) const; - void check_index(size_t index, const char* msg) const NOT_DEBUG_RETURN; public: diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index db2012e9596..a76341a49d3 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -398,7 +398,6 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { HeapWord* result = NULL; for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; - bool preventive_collection_required = false; uint gc_count_before; { @@ -406,32 +405,21 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { // Now that we have the lock, we first retry the allocation in case another // thread changed the region while we were waiting to acquire the lock. - size_t actual_size; - result = _allocator->attempt_allocation(word_size, word_size, &actual_size); + result = _allocator->attempt_allocation_locked(word_size); if (result != NULL) { return result; } - preventive_collection_required = policy()->preventive_collection_required(1); - if (!preventive_collection_required) { - // We've already attempted a lock-free allocation above, so we don't want to - // do it again. Let's jump straight to replacing the active region. - result = _allocator->attempt_allocation_using_new_region(word_size); + // If the GCLocker is active and we are bound for a GC, try expanding young gen. + // This is different to when only GCLocker::needs_gc() is set: try to avoid + // waiting because the GCLocker is active to not wait too long. + if (GCLocker::is_active_and_needs_gc() && policy()->can_expand_young_list()) { + // No need for an ergo message here, can_expand_young_list() does this when + // it returns true. + result = _allocator->attempt_allocation_force(word_size); if (result != NULL) { return result; } - - // If the GCLocker is active and we are bound for a GC, try expanding young gen. - // This is different to when only GCLocker::needs_gc() is set: try to avoid - // waiting because the GCLocker is active to not wait too long. - if (GCLocker::is_active_and_needs_gc() && policy()->can_expand_young_list()) { - // No need for an ergo message here, can_expand_young_list() does this when - // it returns true. - result = _allocator->attempt_allocation_force(word_size); - if (result != NULL) { - return result; - } - } } // Only try a GC if the GCLocker does not signal the need for a GC. Wait until @@ -443,10 +431,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { } if (should_try_gc) { - GCCause::Cause gc_cause = preventive_collection_required ? GCCause::_g1_preventive_collection - : GCCause::_g1_inc_collection_pause; bool succeeded; - result = do_collection_pause(word_size, gc_count_before, &succeeded, gc_cause); + result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_inc_collection_pause); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, @@ -860,7 +846,6 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { HeapWord* result = NULL; for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; - bool preventive_collection_required = false; uint gc_count_before; @@ -868,17 +853,14 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { MutexLocker x(Heap_lock); size_t size_in_regions = humongous_obj_size_in_regions(word_size); - preventive_collection_required = policy()->preventive_collection_required((uint)size_in_regions); - if (!preventive_collection_required) { - // Given that humongous objects are not allocated in young - // regions, we'll first try to do the allocation without doing a - // collection hoping that there's enough space in the heap. - result = humongous_obj_allocate(word_size); - if (result != NULL) { - policy()->old_gen_alloc_tracker()-> - add_allocated_humongous_bytes_since_last_gc(size_in_regions * HeapRegion::GrainBytes); - return result; - } + // Given that humongous objects are not allocated in young + // regions, we'll first try to do the allocation without doing a + // collection hoping that there's enough space in the heap. + result = humongous_obj_allocate(word_size); + if (result != NULL) { + policy()->old_gen_alloc_tracker()-> + add_allocated_humongous_bytes_since_last_gc(size_in_regions * HeapRegion::GrainBytes); + return result; } // Only try a GC if the GCLocker does not signal the need for a GC. Wait until @@ -890,10 +872,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { } if (should_try_gc) { - GCCause::Cause gc_cause = preventive_collection_required ? GCCause::_g1_preventive_collection - : GCCause::_g1_humongous_allocation; bool succeeded; - result = do_collection_pause(word_size, gc_count_before, &succeeded, gc_cause); + result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_humongous_allocation); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, @@ -1466,6 +1446,7 @@ G1CollectedHeap::G1CollectedHeap() : _hot_card_cache(NULL), _rem_set(NULL), _card_set_config(), + _card_set_freelist_pool(G1CardSetConfiguration::num_mem_object_types()), _cm(NULL), _cm_thread(NULL), _cr(NULL), @@ -1874,12 +1855,7 @@ size_t G1CollectedHeap::recalculate_used() const { } bool G1CollectedHeap::is_user_requested_concurrent_full_gc(GCCause::Cause cause) { - switch (cause) { - case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; - case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent; - case GCCause::_wb_conc_mark: return true; - default : return false; - } + return GCCause::is_user_requested_gc(cause) && ExplicitGCInvokesConcurrent; } bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { @@ -2557,16 +2533,17 @@ bool G1CollectedHeap::print_location(outputStream* st, void* addr) const { G1HeapSummary G1CollectedHeap::create_g1_heap_summary() { - size_t eden_used_bytes = _eden.used_bytes(); - size_t survivor_used_bytes = _survivor.used_bytes(); + size_t eden_used_bytes = _monitoring_support->eden_space_used(); + size_t survivor_used_bytes = _monitoring_support->survivor_space_used(); + size_t old_gen_used_bytes = _monitoring_support->old_gen_used(); size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked(); size_t eden_capacity_bytes = (policy()->young_list_target_length() * HeapRegion::GrainBytes) - survivor_used_bytes; VirtualSpaceSummary heap_summary = create_heap_space_summary(); - return G1HeapSummary(heap_summary, heap_used, eden_used_bytes, - eden_capacity_bytes, survivor_used_bytes, num_regions()); + return G1HeapSummary(heap_summary, heap_used, eden_used_bytes, eden_capacity_bytes, + survivor_used_bytes, old_gen_used_bytes, num_regions()); } G1EvacSummary G1CollectedHeap::create_g1_evac_summary(G1EvacStats* stats) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index c52e84b1f92..826e9863311 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ #include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" +#include "gc/g1/g1MonotonicArenaFreePool.hpp" #include "gc/g1/g1NUMA.hpp" #include "gc/g1/g1SurvivorRegions.hpp" #include "gc/g1/g1YoungGCEvacFailureInjector.hpp" @@ -251,7 +252,7 @@ class G1CollectedHeap : public CollectedHeap { // (a) cause == _g1_humongous_allocation, // (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent, // (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent, - // (d) cause == _wb_conc_mark or _wb_breakpoint, + // (d) cause == _wb_breakpoint, // (e) cause == _g1_periodic_collection and +G1PeriodicGCInvokesConcurrent. bool should_do_concurrent_full_gc(GCCause::Cause cause); @@ -787,6 +788,8 @@ class G1CollectedHeap : public CollectedHeap { // Global card set configuration G1CardSetConfiguration _card_set_config; + G1MonotonicArenaFreePool _card_set_freelist_pool; + public: // After a collection pause, reset eden and the collection set. void clear_eden(); @@ -913,6 +916,9 @@ class G1CollectedHeap : public CollectedHeap { // The remembered set. G1RemSet* rem_set() const { return _rem_set; } + const G1MonotonicArenaFreePool* card_set_freelist_pool() const { return &_card_set_freelist_pool; } + G1MonotonicArenaFreePool* card_set_freelist_pool() { return &_card_set_freelist_pool; } + inline G1GCPhaseTimes* phase_times() const; const G1CollectionSet* collection_set() const { return &_collection_set; } diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index 9d1e0347776..a6bbca73709 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -100,10 +100,6 @@ void G1CollectionSet::clear_candidates() { _candidates = NULL; } -bool G1CollectionSet::has_candidates() { - return _candidates != NULL && !_candidates->is_empty(); -} - // Add the heap region at the head of the non-incremental collection set void G1CollectionSet::add_old_region(HeapRegion* hr) { assert_at_safepoint_on_vm_thread(); diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.hpp b/src/hotspot/share/gc/g1/g1CollectionSet.hpp index 68c271f6687..90fe22a2021 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp @@ -223,7 +223,6 @@ class G1CollectionSet { void initialize(uint max_region_length); void clear_candidates(); - bool has_candidates(); void set_candidates(G1CollectionSetCandidates* candidates) { assert(_candidates == NULL, "Trying to replace collection set candidates."); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 46af08bbfc8..17e402a9eb5 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -388,6 +388,7 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _first_overflow_barrier_sync(), _second_overflow_barrier_sync(), + _completed_mark_cycles(0), _has_overflown(false), _concurrent(false), _has_aborted(false), @@ -1010,11 +1011,19 @@ void G1ConcurrentMark::concurrent_cycle_start() { _g1h->trace_heap_before_gc(_gc_tracer_cm); } -void G1ConcurrentMark::concurrent_cycle_end() { +uint G1ConcurrentMark::completed_mark_cycles() const { + return Atomic::load(&_completed_mark_cycles); +} + +void G1ConcurrentMark::concurrent_cycle_end(bool mark_cycle_completed) { _g1h->collector_state()->set_clearing_bitmap(false); _g1h->trace_heap_after_gc(_gc_tracer_cm); + if (mark_cycle_completed) { + Atomic::inc(&_completed_mark_cycles, memory_order_relaxed); + } + if (has_aborted()) { log_info(gc, marking)("Concurrent Mark Abort"); _gc_tracer_cm->report_concurrent_mode_failure(); @@ -3052,8 +3061,10 @@ G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { return; } + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + _total_remset_bytes += g1h->card_set_freelist_pool()->mem_size(); // add static memory usages to remembered set sizes - _total_remset_bytes += G1CardSetFreePool::free_list_pool()->mem_size() + HeapRegionRemSet::static_mem_size(); + _total_remset_bytes += HeapRegionRemSet::static_mem_size(); // Print the footer of the output. log_trace(gc, liveness)(G1PPRL_LINE_PREFIX); log_trace(gc, liveness)(G1PPRL_LINE_PREFIX diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index 8ae487bc1ce..ce7a62fd397 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -327,6 +327,9 @@ class G1ConcurrentMark : public CHeapObj { WorkerThreadsBarrierSync _first_overflow_barrier_sync; WorkerThreadsBarrierSync _second_overflow_barrier_sync; + // Number of completed mark cycles. + volatile uint _completed_mark_cycles; + // This is set by any task, when an overflow on the global data // structures is detected volatile bool _has_overflown; @@ -501,7 +504,7 @@ class G1ConcurrentMark : public CHeapObj { void concurrent_cycle_start(); // Abandon current marking iteration due to a Full GC. bool concurrent_cycle_abort(); - void concurrent_cycle_end(); + void concurrent_cycle_end(bool mark_cycle_completed); // Notifies marking threads to abort. This is a best-effort notification. Does not // guarantee or update any state after the call. Root region scan must not be @@ -593,6 +596,8 @@ class G1ConcurrentMark : public CHeapObj { inline bool do_yield_check(); + uint completed_mark_cycles() const; + bool has_aborted() { return _has_aborted; } void print_summary_info(); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp index 87d614eeece..996fe345f85 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp @@ -334,6 +334,6 @@ void G1ConcurrentMarkThread::concurrent_cycle_end(bool mark_cycle_completed) { G1CollectedHeap::heap()->increment_old_marking_cycles_completed(true /* concurrent */, mark_cycle_completed /* heap_examined */); - _cm->concurrent_cycle_end(); + _cm->concurrent_cycle_end(mark_cycle_completed); ConcurrentGCBreakpoints::notify_active_to_idle(); } diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp index 0e2a075d69d..71e0d70b232 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp @@ -41,7 +41,7 @@ G1FullGCMarker::G1FullGCMarker(G1FullCollector* collector, _oop_stack(), _objarray_stack(), _preserved_stack(preserved_stack), - _mark_closure(worker_id, this, G1CollectedHeap::heap()->ref_processor_stw()), + _mark_closure(worker_id, this, ClassLoaderData::_claim_stw_fullgc_mark, G1CollectedHeap::heap()->ref_processor_stw()), _verify_closure(VerifyOption::G1UseFullMarking), _stack_closure(this), _cld_closure(mark_closure(), ClassLoaderData::_claim_stw_fullgc_mark), diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp index ee77e5044fc..60ece336f80 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp @@ -100,8 +100,6 @@ class G1FullGCMarker : public CHeapObj { // Marking entry points template inline void mark_and_push(T* p); - inline void follow_klass(Klass* k); - inline void follow_cld(ClassLoaderData* cld); inline void follow_marking_stacks(); void complete_marking(OopQueueSet* oop_stacks, diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index cfa0ef9e9d1..3e6d1ad4232 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -101,7 +101,7 @@ inline void G1FullGCMarker::push_objarray(oop obj, size_t index) { } inline void G1FullGCMarker::follow_array(objArrayOop array) { - follow_klass(array->klass()); + mark_closure()->do_klass(array->klass()); // Don't push empty arrays to avoid unnecessary work. if (array->length() > 0) { push_objarray(array, 0); @@ -193,13 +193,4 @@ void G1FullGCMarker::follow_marking_stacks() { } while (!is_empty()); } -inline void G1FullGCMarker::follow_klass(Klass* k) { - oop op = k->class_loader_data()->holder_no_keepalive(); - mark_and_push(&op); -} - -inline void G1FullGCMarker::follow_cld(ClassLoaderData* cld) { - _cld_closure.do_cld(cld); -} - #endif // SHARE_GC_G1_G1FULLGCMARKER_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp b/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp index d3af21e4db0..77bbc44a075 100644 --- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp @@ -58,25 +58,19 @@ class G1FullKeepAliveClosure: public OopClosure { virtual void do_oop(narrowOop* p); }; -class G1MarkAndPushClosure : public OopIterateClosure { +class G1MarkAndPushClosure : public ClaimMetadataVisitingOopIterateClosure { G1FullGCMarker* _marker; uint _worker_id; public: - G1MarkAndPushClosure(uint worker, G1FullGCMarker* marker, ReferenceDiscoverer* ref) : - OopIterateClosure(ref), + G1MarkAndPushClosure(uint worker_id, G1FullGCMarker* marker, int claim, ReferenceDiscoverer* ref) : + ClaimMetadataVisitingOopIterateClosure(claim, ref), _marker(marker), - _worker_id(worker) { } + _worker_id(worker_id) { } template inline void do_oop_work(T* p); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - - virtual bool do_metadata(); - virtual void do_klass(Klass* k); - virtual void do_cld(ClassLoaderData* cld); - virtual void do_method(Method* m); - virtual void do_nmethod(nmethod* nm); }; class G1AdjustClosure : public BasicOopIterateClosure { diff --git a/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp index 738145afcab..73e5fee3dd8 100644 --- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp @@ -51,26 +51,6 @@ inline void G1MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } -inline bool G1MarkAndPushClosure::do_metadata() { - return true; -} - -inline void G1MarkAndPushClosure::do_klass(Klass* k) { - _marker->follow_klass(k); -} - -inline void G1MarkAndPushClosure::do_cld(ClassLoaderData* cld) { - _marker->follow_cld(cld); -} - -inline void G1MarkAndPushClosure::do_method(Method* m) { - m->record_gc_epoch(); -} - -inline void G1MarkAndPushClosure::do_nmethod(nmethod* nm) { - nm->follow_nmethod(this); -} - template inline void G1AdjustClosure::adjust_pointer(T* p) { T heap_oop = RawAccess<>::oop_load(p); if (CompressedOops::is_null(heap_oop)) { diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp index 70621ac3449..a453aebc2fa 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -50,7 +50,7 @@ G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support, _active(), _tracer_mark(&_timer, _tracer), _soft_refs(clear_soft, _g1h->soft_ref_policy()), - _monitoring_scope(monitoring_support, true /* full_gc */, true /* all_memory_pools_affected */), + _monitoring_scope(monitoring_support), _heap_printer(_g1h), _region_compaction_threshold(do_maximal_compaction ? HeapRegion::GrainWords : diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp index 80dce2535dd..3863be8358b 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -55,7 +55,7 @@ class G1FullGCScope : public StackObj { IsGCActiveMark _active; G1FullGCJFRTracerMark _tracer_mark; ClearedAllSoftRefs _soft_refs; - G1MonitoringScope _monitoring_scope; + G1FullGCMonitoringScope _monitoring_scope; G1HeapPrinterMark _heap_printer; size_t _region_compaction_threshold; diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 83a22a5e820..b799a12531b 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -412,8 +412,7 @@ double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { const double pre_concurrent_start_ms = average_time_ms(ResetMarkingState) + average_time_ms(NoteStartOfMark); - const double sum_ms = _root_region_scan_wait_time_ms + - _cur_prepare_tlab_time_ms + + const double sum_ms = _cur_prepare_tlab_time_ms + _cur_concatenate_dirty_card_logs_time_ms + _recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms + @@ -423,9 +422,6 @@ double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { info_time("Pre Evacuate Collection Set", sum_ms); - if (_root_region_scan_wait_time_ms > 0.0) { - debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); - } debug_time("Prepare TLABs", _cur_prepare_tlab_time_ms); debug_time("Concatenate Dirty Card Logs", _cur_concatenate_dirty_card_logs_time_ms); debug_time("Choose Collection Set", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); @@ -557,6 +553,10 @@ void G1GCPhaseTimes::print_other(double accounted_ms) const { } void G1GCPhaseTimes::print(bool evacuation_failed) { + if (_root_region_scan_wait_time_ms > 0.0) { + debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); + } + // Check if some time has been recorded for verification and only then print // the message. We do not use Verify*GC here to print because VerifyGCType // further limits actual verification. @@ -565,10 +565,17 @@ void G1GCPhaseTimes::print(bool evacuation_failed) { } double accounted_ms = 0.0; + + accounted_ms += _root_region_scan_wait_time_ms; + accounted_ms += _cur_verify_before_time_ms; + accounted_ms += print_pre_evacuate_collection_set(); accounted_ms += print_evacuate_initial_collection_set(); accounted_ms += print_evacuate_optional_collection_set(); accounted_ms += print_post_evacuate_collection_set(evacuation_failed); + + accounted_ms += _cur_verify_after_time_ms; + print_other(accounted_ms); // See above comment on the _cur_verify_before_time_ms check. diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index e8bbb062dd4..680e989c853 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -88,12 +88,13 @@ class G1OldGenerationCounters : public G1GenerationCounters { G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : _g1h(g1h), - _incremental_memory_manager("G1 Young Generation", "end of minor GC"), + _young_gc_memory_manager("G1 Young Generation", "end of minor GC"), _full_gc_memory_manager("G1 Old Generation", "end of major GC"), + _conc_gc_memory_manager("G1 Concurrent GC", "end of concurrent GC pause"), _eden_space_pool(NULL), _survivor_space_pool(NULL), _old_gen_pool(NULL), - _incremental_collection_counters(NULL), + _young_collection_counters(NULL), _full_collection_counters(NULL), _conc_collection_counters(NULL), _young_gen_counters(NULL), @@ -120,7 +121,7 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : // // name "collector.0". In a generational collector this would be the // young generation collection. - _incremental_collection_counters = + _young_collection_counters = new CollectorCounters("G1 young collection pauses", 0); // name "collector.1". In a generational collector this would be the // old generation collection. @@ -199,9 +200,11 @@ void G1MonitoringSupport::initialize_serviceability() { _full_gc_memory_manager.add_pool(_survivor_space_pool); _full_gc_memory_manager.add_pool(_old_gen_pool); - _incremental_memory_manager.add_pool(_eden_space_pool); - _incremental_memory_manager.add_pool(_survivor_space_pool); - _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); + _conc_gc_memory_manager.add_pool(_old_gen_pool); + + _young_gc_memory_manager.add_pool(_eden_space_pool); + _young_gc_memory_manager.add_pool(_survivor_space_pool); + _young_gc_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); } MemoryUsage G1MonitoringSupport::memory_usage() { @@ -210,9 +213,10 @@ MemoryUsage G1MonitoringSupport::memory_usage() { } GrowableArray G1MonitoringSupport::memory_managers() { - GrowableArray memory_managers(2); - memory_managers.append(&_incremental_memory_manager); + GrowableArray memory_managers(3); + memory_managers.append(&_young_gc_memory_manager); memory_managers.append(&_full_gc_memory_manager); + memory_managers.append(&_conc_gc_memory_manager); return memory_managers; } @@ -294,7 +298,7 @@ void G1MonitoringSupport::update_sizes() { if (UsePerfData) { _eden_space_counters->update_capacity(pad_capacity(_eden_space_committed)); _eden_space_counters->update_used(_eden_space_used); - // only the "to" survivor space is active, so we don't need to + // only the "to" survivor space is active, so we don't need to // update the counters for the "from" survivor space _to_space_counters->update_capacity(pad_capacity(_survivor_space_committed)); _to_space_counters->update_used(_survivor_space_used); @@ -344,10 +348,13 @@ MemoryUsage G1MonitoringSupport::old_gen_memory_usage(size_t initial_size, size_ max_size); } -G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* monitoring_support, bool full_gc, bool all_memory_pools_affected) : +G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* monitoring_support, + CollectorCounters* collection_counters, + GCMemoryManager* gc_memory_manager, + bool all_memory_pools_affected) : _monitoring_support(monitoring_support), - _tcs(full_gc ? monitoring_support->_full_collection_counters : monitoring_support->_incremental_collection_counters), - _tms(full_gc ? &monitoring_support->_full_gc_memory_manager : &monitoring_support->_incremental_memory_manager, + _tcs(collection_counters), + _tms(gc_memory_manager, G1CollectedHeap::heap()->gc_cause(), all_memory_pools_affected) { } @@ -356,3 +363,23 @@ G1MonitoringScope::~G1MonitoringScope() { // Needs to be called after updating pool sizes. MemoryService::track_memory_usage(); } + +G1YoungGCMonitoringScope::G1YoungGCMonitoringScope(G1MonitoringSupport* monitoring_support, + bool all_memory_pools_affected) : + G1MonitoringScope(monitoring_support, + monitoring_support->_young_collection_counters, + &monitoring_support->_young_gc_memory_manager, + all_memory_pools_affected) { +} + +G1FullGCMonitoringScope::G1FullGCMonitoringScope(G1MonitoringSupport* monitoring_support) : + G1MonitoringScope(monitoring_support, + monitoring_support->_full_collection_counters, + &monitoring_support->_full_gc_memory_manager) { +} + +G1ConcGCMonitoringScope::G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support) : + G1MonitoringScope(monitoring_support, + monitoring_support->_conc_collection_counters, + &monitoring_support->_conc_gc_memory_manager) { +} diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp index 0e35b54d676..bae4ade0e43 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp @@ -121,24 +121,27 @@ class MemoryPool; class G1MonitoringSupport : public CHeapObj { friend class VMStructs; - friend class G1MonitoringScope; + friend class G1YoungGCMonitoringScope; + friend class G1FullGCMonitoringScope; + friend class G1ConcGCMonitoringScope; G1CollectedHeap* _g1h; // java.lang.management MemoryManager and MemoryPool support - GCMemoryManager _incremental_memory_manager; + GCMemoryManager _young_gc_memory_manager; GCMemoryManager _full_gc_memory_manager; + GCMemoryManager _conc_gc_memory_manager; MemoryPool* _eden_space_pool; MemoryPool* _survivor_space_pool; MemoryPool* _old_gen_pool; // jstat performance counters - // incremental collections both young and mixed - CollectorCounters* _incremental_collection_counters; + // young stop-the-world collections (including mixed) + CollectorCounters* _young_collection_counters; // full stop-the-world collections CollectorCounters* _full_collection_counters; - // stop-the-world phases in G1 + // stop-the-world phases in G1 concurrent collection CollectorCounters* _conc_collection_counters; // young collection set counters. The _eden_counters, // _from_counters, and _to_counters are associated with @@ -210,10 +213,6 @@ class G1MonitoringSupport : public CHeapObj { void update_eden_size(); - CollectorCounters* conc_collection_counters() { - return _conc_collection_counters; - } - // Monitoring support used by // MemoryService // jstat counters @@ -241,9 +240,26 @@ class G1MonitoringScope : public StackObj { G1MonitoringSupport* _monitoring_support; TraceCollectorStats _tcs; TraceMemoryManagerStats _tms; -public: - G1MonitoringScope(G1MonitoringSupport* monitoring_support, bool full_gc, bool all_memory_pools_affected); +protected: + G1MonitoringScope(G1MonitoringSupport* monitoring_support, + CollectorCounters* collection_counters, + GCMemoryManager* gc_memory_manager, + bool all_memory_pools_affected = true); ~G1MonitoringScope(); }; +class G1YoungGCMonitoringScope : public G1MonitoringScope { +public: + G1YoungGCMonitoringScope(G1MonitoringSupport* monitoring_support, bool all_memory_pools_affected); +}; + +class G1FullGCMonitoringScope : public G1MonitoringScope { +public: + G1FullGCMonitoringScope(G1MonitoringSupport* monitoring_support); +}; + +class G1ConcGCMonitoringScope : public G1MonitoringScope { +public: + G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support); +}; #endif // SHARE_GC_G1_G1MONITORINGSUPPORT_HPP diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp index e73c386025e..4ba4469bd96 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp @@ -27,6 +27,7 @@ #include "gc/g1/g1CardSetMemory.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" +#include "gc/g1/g1MonotonicArenaFreePool.hpp" #include "gc/g1/g1_globals.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/gc_globals.hpp" @@ -53,7 +54,9 @@ bool G1MonotonicArenaFreeMemoryTask::calculate_return_infos(jlong deadline) { // Ignore the deadline in this step as it is very short. G1MonotonicArenaMemoryStats used = _total_used; - G1MonotonicArenaMemoryStats free = G1MonotonicArenaFreePool::free_list_sizes(); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1MonotonicArenaFreePool* freelist_pool = g1h->card_set_freelist_pool(); + G1MonotonicArenaMemoryStats free = freelist_pool->memory_sizes(); _return_info = new G1ReturnMemoryProcessorSet(used.num_pools()); for (uint i = 0; i < used.num_pools(); i++) { @@ -69,7 +72,7 @@ bool G1MonotonicArenaFreeMemoryTask::calculate_return_infos(jlong deadline) { _return_info->append(new G1ReturnMemoryProcessor(return_to_vm_size)); } - G1MonotonicArenaFreePool::update_unlink_processors(_return_info); + freelist_pool->update_unlink_processors(_return_info); return false; } diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp index 1f85c265e47..76df02d2a71 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp @@ -44,10 +44,9 @@ void G1MonotonicArenaMemoryStats::clear() { } void G1MonotonicArenaFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { - uint num_free_lists = _freelist_pool.num_free_lists(); - for (uint i = 0; i < num_free_lists; i++) { - unlink_processor->at(i)->visit_free_list(_freelist_pool.free_list(i)); + for (uint i = 0; i < num_free_lists(); i++) { + unlink_processor->at(i)->visit_free_list(free_list(i)); } } @@ -148,8 +147,6 @@ bool G1MonotonicArenaFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadl return _first != nullptr; } -G1MonotonicArenaFreePool G1MonotonicArenaFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); - G1MonotonicArenaFreePool::G1MonotonicArenaFreePool(uint num_free_lists) : _num_free_lists(num_free_lists) { @@ -184,8 +181,8 @@ size_t G1MonotonicArenaFreePool::mem_size() const { return result; } -void G1MonotonicArenaFreePool::print_on(outputStream* out) { - out->print_cr(" Free Pool: size %zu", free_list_pool()->mem_size()); +void G1MonotonicArenaFreePool::print_on(outputStream* out) const { + out->print_cr(" Free Pool: size %zu", mem_size()); for (uint i = 0; i < _num_free_lists; i++) { FormatBuffer<> fmt(" %s", G1CardSetConfiguration::mem_object_type_name_str(i)); _free_lists[i].print_on(out, fmt); diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp index 91486bf7927..2746315a8a8 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp @@ -58,20 +58,15 @@ class G1MonotonicArenaMemoryStats { // e.g. G1CardSetAllocators::_arena class G1MonotonicArenaFreePool { using SegmentFreeList = G1MonotonicArena::SegmentFreeList; - // The global free pool. - static G1MonotonicArenaFreePool _freelist_pool; const uint _num_free_lists; SegmentFreeList* _free_lists; public: - static G1MonotonicArenaFreePool* free_list_pool() { return &_freelist_pool; } - static G1MonotonicArenaMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); } - class G1ReturnMemoryProcessor; typedef GrowableArrayCHeap G1ReturnMemoryProcessorSet; - static void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors); + void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors); explicit G1MonotonicArenaFreePool(uint num_free_lists); ~G1MonotonicArenaFreePool(); @@ -86,7 +81,7 @@ class G1MonotonicArenaFreePool { G1MonotonicArenaMemoryStats memory_sizes() const; size_t mem_size() const; - void print_on(outputStream* out); + void print_on(outputStream* out) const; }; // Data structure containing current in-progress state for returning memory to the diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 78ab9b5af94..f7940445503 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -71,8 +71,6 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _reserve_regions(0), _young_gen_sizer(), _free_regions_at_end_of_collection(0), - _predicted_surviving_bytes_from_survivor(0), - _predicted_surviving_bytes_from_old(0), _rs_length(0), _pending_cards_at_gc_start(0), _concurrent_start_to_mixed(), @@ -188,6 +186,7 @@ uint G1Policy::calculate_desired_eden_length_by_mmu() const { } void G1Policy::update_young_length_bounds() { + assert(!Universe::is_fully_initialized() || SafepointSynchronize::is_at_safepoint(), "must be"); bool for_young_only_phase = collector_state()->in_young_only_phase(); update_young_length_bounds(_analytics->predict_pending_cards(for_young_only_phase), _analytics->predict_rs_length(for_young_only_phase)); @@ -224,14 +223,16 @@ void G1Policy::update_young_length_bounds(size_t pending_cards, size_t rs_length // // - sizer min/max bounds on young gen // - pause time goal for whole young gen evacuation -// - MMU goal influencing eden to make GCs spaced apart. -// - a minimum one eden region length. +// - MMU goal influencing eden to make GCs spaced apart +// - if after a GC, request at least one eden region to avoid immediate full gcs // -// We may enter with already allocated eden and survivor regions, that may be -// higher than the maximum, or the above goals may result in a desired value -// smaller than are already allocated. -// The main reason is revising young length, with or without the GCLocker being -// active. +// We may enter with already allocated eden and survivor regions because there +// are survivor regions (after gc). Young gen revising can call this method at any +// time too. +// +// For this method it does not matter if the above goals may result in a desired +// value smaller than what is already allocated or what can actually be allocated. +// This return value is only an expectation. // uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_length) const { uint min_young_length_by_sizer = _young_gen_sizer.min_desired_young_length(); @@ -240,12 +241,6 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le assert(min_young_length_by_sizer >= 1, "invariant"); assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); - // Absolute minimum eden length. - // Enforcing a minimum eden length helps at startup when the predictors are not - // yet trained on the application to avoid unnecessary (but very short) full gcs - // on very small (initial) heaps. - uint const MinDesiredEdenLength = 1; - // Calculate the absolute and desired min bounds first. // This is how many survivor regions we already have. @@ -253,9 +248,13 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le // Size of the already allocated young gen. const uint allocated_young_length = _g1h->young_regions_count(); // This is the absolute minimum young length that we can return. Ensure that we - // don't go below any user-defined minimum bound; but we might have already - // allocated more than that for various reasons. In this case, use that. - uint absolute_min_young_length = MAX2(allocated_young_length, min_young_length_by_sizer); + // don't go below any user-defined minimum bound. Also, we must have at least + // one eden region, to ensure progress. But when revising during the ensuing + // mutator phase we might have already allocated more than either of those, in + // which case use that. + uint absolute_min_young_length = MAX3(min_young_length_by_sizer, + survivor_length + 1, + allocated_young_length); // Calculate the absolute max bounds. After evac failure or when revising the // young length we might have exceeded absolute min length or absolute_max_length, // so adjust the result accordingly. @@ -277,10 +276,8 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le // Incorporate MMU concerns; assume that it overrides the pause time // goal, as the default value has been chosen to effectively disable it. - // Also request at least one eden region, see above for reasons. - uint desired_eden_length = MAX3(desired_eden_length_by_pause, - desired_eden_length_by_mmu, - MinDesiredEdenLength); + uint desired_eden_length = MAX2(desired_eden_length_by_pause, + desired_eden_length_by_mmu); desired_young_length = desired_eden_length + survivor_length; } else { @@ -297,13 +294,11 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le "absolute min young length %u " "absolute max young length %u " "desired eden length by mmu %u " - "desired eden length by pause %u " - "desired eden length by default %u", + "desired eden length by pause %u ", desired_young_length, survivor_length, allocated_young_length, absolute_min_young_length, absolute_max_young_length, desired_eden_length_by_mmu, - desired_eden_length_by_pause, - MinDesiredEdenLength); + desired_eden_length_by_pause); assert(desired_young_length >= allocated_young_length, "must be"); return desired_young_length; @@ -566,7 +561,6 @@ void G1Policy::record_full_collection_end() { // also call this on any additional surv rate groups _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_survival_estimates_for_next_collection(); _survivor_surv_rate_group->reset(); update_young_length_bounds(); @@ -881,8 +875,6 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_survival_estimates_for_next_collection(); - // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely // that in this case we are not running in a "normal" operating mode. if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) { @@ -1561,88 +1553,6 @@ void G1Policy::calculate_optional_collection_set_regions(G1CollectionSetCandidat num_optional_regions, max_optional_regions, total_prediction_ms); } -// Number of regions required to store the given number of bytes, taking -// into account the target amount of wasted space in PLABs. -static size_t get_num_regions_adjust_for_plab_waste(size_t byte_count) { - size_t byte_count_adjusted = byte_count * (size_t)(100 + TargetPLABWastePct) / 100.0; - - // Round up the region count - return (byte_count_adjusted + HeapRegion::GrainBytes - 1) / HeapRegion::GrainBytes; -} - -bool G1Policy::preventive_collection_required(uint alloc_region_count) { - if (!G1UsePreventiveGC || !Universe::is_fully_initialized()) { - // Don't attempt any preventive GC's if the feature is disabled, - // or before initialization is complete. - return false; - } - - if (_g1h->young_regions_count() == 0 && !_collection_set->has_candidates()) { - return false; - } - - uint eden_count = _g1h->eden_regions_count(); - size_t const eden_surv_bytes_pred = _eden_surv_rate_group->accum_surv_rate_pred(eden_count) * HeapRegion::GrainBytes; - size_t const total_young_predicted_surviving_bytes = eden_surv_bytes_pred + _predicted_surviving_bytes_from_survivor; - - uint required_regions = (uint)(get_num_regions_adjust_for_plab_waste(total_young_predicted_surviving_bytes) + - get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_old)); - - if (required_regions > _g1h->num_free_or_available_regions() - alloc_region_count) { - log_debug(gc, ergo, cset)("Preventive GC, insufficient free or available regions. " - "Predicted need %u. Curr Eden %u (Pred %u). Curr Survivor %u (Pred %u). Curr Old %u (Pred %u) Free or Avail %u (Free %u) Alloc %u", - required_regions, - eden_count, - (uint)get_num_regions_adjust_for_plab_waste(eden_surv_bytes_pred), - _g1h->survivor_regions_count(), - (uint)get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_survivor), - _g1h->old_regions_count(), - (uint)get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_old), - _g1h->num_free_or_available_regions(), - _g1h->num_free_regions(), - alloc_region_count); - - return true; - } - - return false; -} - -void G1Policy::update_survival_estimates_for_next_collection() { - // Predict the number of bytes of surviving objects from survivor and old - // regions and update the associated members. - - // Survivor regions - size_t survivor_bytes = 0; - const GrowableArray* survivor_regions = _g1h->survivor()->regions(); - for (GrowableArrayIterator it = survivor_regions->begin(); - it != survivor_regions->end(); - ++it) { - survivor_bytes += predict_bytes_to_copy(*it); - } - - _predicted_surviving_bytes_from_survivor = survivor_bytes; - - // Old regions - if (!_collection_set->has_candidates()) { - _predicted_surviving_bytes_from_old = 0; - return; - } - - // Use the minimum old gen collection set as conservative estimate for the number - // of regions to take for this calculation. - G1CollectionSetCandidates *candidates = _collection_set->candidates(); - uint iterate_count = MIN2(candidates->num_remaining(), calc_min_old_cset_length(candidates)); - uint current_index = candidates->cur_idx(); - size_t old_bytes = 0; - for (uint i = 0; i < iterate_count; i++) { - HeapRegion *region = candidates->at(current_index + i); - old_bytes += predict_bytes_to_copy(region); - } - - _predicted_surviving_bytes_from_old = old_bytes; -} - void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) { start_adding_survivor_regions(); diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index c7b04bce49f..9b5dd6c4ed0 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -101,11 +101,6 @@ class G1Policy: public CHeapObj { uint _free_regions_at_end_of_collection; - // These values are predictions of how much we think will survive in each - // section of the heap. - size_t _predicted_surviving_bytes_from_survivor; - size_t _predicted_surviving_bytes_from_old; - size_t _rs_length; size_t _pending_cards_at_gc_start; @@ -359,11 +354,6 @@ class G1Policy: public CHeapObj { double time_remaining_ms, uint& num_optional_regions); - // Returns whether a collection should be done proactively, taking into - // account the current number of free regions and the expected survival - // rates in each section of the heap. - bool preventive_collection_required(uint region_count); - private: // Predict the number of bytes of surviving objects from survivor and old diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index e4377885f7f..ff59b3a1189 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1031,7 +1031,7 @@ class G1MergeHeapRootsTask : public WorkerTask { G1MergeHeapRootsPrefetchCache(G1CardTable::dirty_card_val()), _merge_card_cl(merge_card_cl) { } - ~G1MergeCardSetCache() { + void flush() { for (uint i = 0; i < CacheSize; i++) { _merge_card_cl->mark_card(push(&_dummy_card)); } @@ -1120,7 +1120,10 @@ class G1MergeHeapRootsTask : public WorkerTask { return false; } - G1MergeCardSetStats stats() const { return _stats; } + G1MergeCardSetStats stats() { + _merge_card_set_cache.flush(); + return _stats; + } }; // Closure to make sure that the marking bitmap is clear for any old region in @@ -1187,11 +1190,10 @@ class G1MergeHeapRootsTask : public WorkerTask { // Visitor for the remembered sets of humongous candidate regions to merge their // remembered set into the card table. class G1FlushHumongousCandidateRemSets : public HeapRegionIndexClosure { - G1RemSetScanState* _scan_state; - G1MergeCardSetStats _merge_stats; + G1MergeCardSetClosure _cl; public: - G1FlushHumongousCandidateRemSets(G1RemSetScanState* scan_state) : _scan_state(scan_state), _merge_stats() { } + G1FlushHumongousCandidateRemSets(G1RemSetScanState* scan_state) : _cl(scan_state) { } bool do_heap_region_index(uint region_index) override { G1CollectedHeap* g1h = G1CollectedHeap::heap(); @@ -1208,12 +1210,8 @@ class G1MergeHeapRootsTask : public WorkerTask { guarantee(r->rem_set()->occupancy_less_or_equal_than(G1EagerReclaimRemSetThreshold), "Found a not-small remembered set here. This is inconsistent with previous assumptions."); - G1MergeCardSetStats stats; - { - G1MergeCardSetClosure cl(_scan_state); - cl.merge_card_set_for_region(r); - stats = cl.stats(); - } + + _cl.merge_card_set_for_region(r); // We should only clear the card based remembered set here as we will not // implicitly rebuild anything else during eager reclaim. Note that at the moment @@ -1233,7 +1231,9 @@ class G1MergeHeapRootsTask : public WorkerTask { return false; } - size_t merged(uint i) const { return _merge_stats.merged(i); } + G1MergeCardSetStats stats() { + return _cl.stats(); + } }; // Visitor for the log buffer entries to merge them into the card table. @@ -1347,24 +1347,22 @@ class G1MergeHeapRootsTask : public WorkerTask { G1FlushHumongousCandidateRemSets cl(_scan_state); g1h->heap_region_iterate(&cl); + G1MergeCardSetStats stats = cl.stats(); for (uint i = 0; i < G1GCPhaseTimes::MergeRSContainersSentinel; i++) { - p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged(i), i); + p->record_or_add_thread_work_item(merge_remset_phase, worker_id, stats.merged(i), i); } } } { // 2. collection set - G1MergeCardSetStats stats; - { - G1MergeCardSetClosure merge(_scan_state); - G1ClearBitmapClosure clear(g1h); - G1CombinedClosure combined(&merge, &clear); + G1MergeCardSetClosure merge(_scan_state); + G1ClearBitmapClosure clear(g1h); + G1CombinedClosure combined(&merge, &clear); - g1h->collection_set_iterate_increment_from(&combined, nullptr, worker_id); - stats = merge.stats(); - } + g1h->collection_set_iterate_increment_from(&combined, nullptr, worker_id); + G1MergeCardSetStats stats = merge.stats(); for (uint i = 0; i < G1GCPhaseTimes::MergeRSContainersSentinel; i++) { p->record_or_add_thread_work_item(merge_remset_phase, worker_id, stats.merged(i), i); diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index a4b517111f7..d8ec513957a 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -285,7 +285,8 @@ class HRRSStatsIter: public HeapRegionClosure { rem_set->occupied()); HeapRegionRemSet::print_static_mem_size(out); - G1CardSetFreePool::free_list_pool()->print_on(out); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + g1h->card_set_freelist_pool()->print_on(out); // Code root statistics HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index e0e3d7e25ba..8ccd7f2c9fb 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -123,15 +123,10 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size, VM_CollectForAllocation(word_size, gc_count_before, gc_cause), _gc_succeeded(false) {} -bool VM_G1CollectForAllocation::should_try_allocation_before_gc() { - // Don't allocate before a preventive GC. - return _gc_cause != GCCause::_g1_preventive_collection; -} - void VM_G1CollectForAllocation::doit() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (should_try_allocation_before_gc() && _word_size > 0) { + if (_word_size > 0) { // An allocation has been requested. So, try to do that first. _result = g1h->attempt_allocation_at_safepoint(_word_size, false /* expect_null_cur_alloc_region */); @@ -172,7 +167,7 @@ void VM_G1PauseConcurrent::doit() { GCTraceTimePauseTimer timer(_message, g1h->concurrent_mark()->gc_timer_cm()); GCTraceTimeDriver t(&logger, &timer); - TraceCollectorStats tcs(g1h->monitoring_support()->conc_collection_counters()); + G1ConcGCMonitoringScope monitoring_scope(g1h->monitoring_support()); SvcGCMarker sgcm(SvcGCMarker::CONCURRENT); IsGCActiveMark x; diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index edf53073789..cfca9e21d07 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -77,9 +77,6 @@ class VM_G1CollectForAllocation : public VM_CollectForAllocation { virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; } virtual void doit(); bool gc_succeeded() const { return _gc_succeeded; } - -private: - bool should_try_allocation_before_gc(); }; // Concurrent G1 stop-the-world operations such as remark and cleanup. diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index a9999b80236..88bf355dfce 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -1056,9 +1056,8 @@ void G1YoungCollector::collect() { // JFR G1YoungGCJFRTracerMark jtm(gc_timer_stw(), gc_tracer_stw(), _gc_cause); // JStat/MXBeans - G1MonitoringScope ms(monitoring_support(), - false /* full_gc */, - collector_state()->in_mixed_phase() /* all_memory_pools_affected */); + G1YoungGCMonitoringScope ms(monitoring_support(), + collector_state()->in_mixed_phase() /* all_memory_pools_affected */); // Create the heap printer before internal pause timing to have // heap information printed as last part of detailed GC log. G1HeapPrinterMark hpm(_g1h); diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index 0e5a800e6a5..a4d7aea17ca 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -59,7 +59,7 @@ HeapRegionRemSet::HeapRegionRemSet(HeapRegion* hr, G1CardSetConfiguration* config) : _m(Mutex::service - 1, FormatBuffer<128>("HeapRegionRemSet#%u_lock", hr->hrm_index())), _code_roots(), - _card_set_mm(config, G1MonotonicArenaFreePool::free_list_pool()), + _card_set_mm(config, G1CollectedHeap::heap()->card_set_freelist_pool()), _card_set(config, &_card_set_mm), _hr(hr), _state(Untracked) { } diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp index 67c6d421d86..f4a1fb3a87f 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp @@ -141,7 +141,7 @@ class HeapRegionRemSet : public CHeapObj { // Returns the memory occupancy of all static data structures associated // with remembered sets. static size_t static_mem_size() { - return G1CardSet::static_mem_size() + G1CodeRootSet::static_mem_size() + sizeof(G1CardSetFreePool); + return G1CardSet::static_mem_size() + G1CodeRootSet::static_mem_size(); } static void print_static_mem_size(outputStream* out); diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 9275b1c3190..e77aba9c1f0 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -314,9 +314,12 @@ void MutableNUMASpace::bias_region(MemRegion mr, int lgrp_id) { assert(region().contains(aligned_region), "Sanity"); // First we tell the OS which page size we want in the given range. The underlying // large page can be broken down if we require small pages. - os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), page_size()); + const size_t os_align = UseLargePages ? page_size() : os::vm_page_size(); + os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); // Then we uncommit the pages in the range. - os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), page_size()); + // The alignment_hint argument must be less than or equal to the small page + // size if not using large pages or else this function does nothing. + os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); // And make them local/first-touch biased. os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), lgrp_id); } @@ -373,12 +376,6 @@ void MutableNUMASpace::update() { } } - if (NUMAStats) { - for (int i = 0; i < lgrp_spaces()->length(); i++) { - lgrp_spaces()->at(i)->accumulate_statistics(page_size()); - } - } - scan_pages(NUMAPageScanRate); } @@ -402,12 +399,6 @@ void MutableNUMASpace::accumulate_statistics() { } increment_samples_count(); } - - if (NUMAStats) { - for (int i = 0; i < lgrp_spaces()->length(); i++) { - lgrp_spaces()->at(i)->accumulate_statistics(page_size()); - } - } } // Get the current size of a chunk. @@ -867,14 +858,11 @@ void MutableNUMASpace::print_on(outputStream* st) const { lgrp_spaces()->at(i)->accumulate_statistics(page_size()); } st->print(" local/remote/unbiased/uncommitted: " SIZE_FORMAT "K/" - SIZE_FORMAT "K/" SIZE_FORMAT "K/" SIZE_FORMAT - "K, large/small pages: " SIZE_FORMAT "/" SIZE_FORMAT "\n", + SIZE_FORMAT "K/" SIZE_FORMAT "K/" SIZE_FORMAT "K\n", ls->space_stats()->_local_space / K, ls->space_stats()->_remote_space / K, ls->space_stats()->_unbiased_space / K, - ls->space_stats()->_uncommited_space / K, - ls->space_stats()->_large_pages, - ls->space_stats()->_small_pages); + ls->space_stats()->_uncommited_space / K); } } } @@ -892,28 +880,25 @@ void MutableNUMASpace::LGRPSpace::accumulate_statistics(size_t page_size) { clear_space_stats(); char *start = (char*)align_up(space()->bottom(), page_size); char* end = (char*)align_down(space()->end(), page_size); - if (start < end) { - for (char *p = start; p < end;) { - os::page_info info; - if (os::get_page_info(p, &info)) { - if (info.size > 0) { - if (info.size > (size_t)os::vm_page_size()) { - space_stats()->_large_pages++; - } else { - space_stats()->_small_pages++; - } - if (info.lgrp_id == lgrp_id()) { - space_stats()->_local_space += info.size; - } else { - space_stats()->_remote_space += info.size; - } - p += info.size; - } else { - p += os::vm_page_size(); + for (char *p = start; p < end; ) { + static const size_t PagesPerIteration = 128; + const void* pages[PagesPerIteration]; + int lgrp_ids[PagesPerIteration]; + + size_t npages = 0; + for (; npages < PagesPerIteration && p < end; p += os::vm_page_size()) { + pages[npages++] = p; + } + + if (os::numa_get_group_ids_for_range(pages, lgrp_ids, npages)) { + for (size_t i = 0; i < npages; i++) { + if (lgrp_ids[i] < 0) { space_stats()->_uncommited_space += os::vm_page_size(); + } else if (lgrp_ids[i] == lgrp_id()) { + space_stats()->_local_space += os::vm_page_size(); + } else { + space_stats()->_remote_space += os::vm_page_size(); } - } else { - return; } } } diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp index 881f280c4b4..2e2e54bd3cd 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -73,15 +73,12 @@ class MutableNUMASpace : public MutableSpace { struct SpaceStats { size_t _local_space, _remote_space, _unbiased_space, _uncommited_space; - size_t _large_pages, _small_pages; SpaceStats() { _local_space = 0; _remote_space = 0; _unbiased_space = 0; _uncommited_space = 0; - _large_pages = 0; - _small_pages = 0; } }; diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 428e09f1bdc..808fa4a74dd 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -100,7 +100,7 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i case ParallelRootType::code_cache: { - MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations, true /* keepalive nmethods */); + MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations, false /* keepalive nmethods */); ScavengableNMethods::nmethods_do(&code_closure); } break; @@ -270,7 +270,7 @@ class PSThreadRootsTaskClosure : public ThreadClosure { PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(_worker_id); PSScavengeRootsClosure roots_closure(pm); - MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations, true /* keepalive nmethods */); + MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations, false /* keepalive nmethods */); thread->oops_do(&roots_closure, &roots_in_blobs); diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index 290c64bf92c..ffd6ddfbf61 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -185,12 +185,13 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { { StrongRootsScope srs(0); - gch->full_process_roots(false, // not the adjust phase - GenCollectedHeap::SO_None, - ClassUnloading, // only strong roots if ClassUnloading - // is enabled - &follow_root_closure, - &follow_cld_closure); + CLDClosure* weak_cld_closure = ClassUnloading ? NULL : &follow_cld_closure; + MarkingCodeBlobClosure mark_code_closure(&follow_root_closure, !CodeBlobToOopClosure::FixRelocations, true); + gch->process_roots(GenCollectedHeap::SO_None, + &follow_root_closure, + &follow_cld_closure, + weak_cld_closure, + &mark_code_closure); } // Process reference objects found during marking @@ -262,15 +263,12 @@ void GenMarkSweep::mark_sweep_phase3() { ClassLoaderDataGraph::verify_claimed_marks_cleared(ClassLoaderData::_claim_stw_fullgc_adjust); - { - StrongRootsScope srs(0); - - gch->full_process_roots(true, // this is the adjust phase - GenCollectedHeap::SO_AllCodeCache, - false, // all roots - &adjust_pointer_closure, - &adjust_cld_closure); - } + CodeBlobToOopClosure code_closure(&adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations); + gch->process_roots(GenCollectedHeap::SO_AllCodeCache, + &adjust_pointer_closure, + &adjust_cld_closure, + &adjust_cld_closure, + &code_closure); gch->gen_process_weak_roots(&adjust_pointer_closure); diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp index e9667d4e346..5647de2748e 100644 --- a/src/hotspot/share/gc/serial/markSweep.cpp +++ b/src/hotspot/share/gc/serial/markSweep.cpp @@ -61,11 +61,11 @@ StringDedup::Requests* MarkSweep::_string_dedup_requests = NULL; MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; -MarkAndPushClosure MarkSweep::mark_and_push_closure; +MarkAndPushClosure MarkSweep::mark_and_push_closure(ClassLoaderData::_claim_stw_fullgc_mark); CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_stw_fullgc_mark); CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_stw_fullgc_adjust); -template inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) { +template void MarkSweep::KeepAliveClosure::do_oop_work(T* p) { mark_and_push(p); } @@ -75,15 +75,15 @@ void MarkSweep::push_objarray(oop obj, size_t index) { _objarray_stack.push(task); } -inline void MarkSweep::follow_array(objArrayOop array) { - MarkSweep::follow_klass(array->klass()); +void MarkSweep::follow_array(objArrayOop array) { + mark_and_push_closure.do_klass(array->klass()); // Don't push empty arrays to avoid unnecessary work. if (array->length() > 0) { MarkSweep::push_objarray(array, 0); } } -inline void MarkSweep::follow_object(oop obj) { +void MarkSweep::follow_object(oop obj) { assert(obj->is_gc_marked(), "should be marked"); if (obj->is_objArray()) { // Handle object arrays explicitly to allow them to @@ -128,7 +128,7 @@ MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure; void MarkSweep::FollowStackClosure::do_void() { follow_stack(); } -template inline void MarkSweep::follow_root(T* p) { +template void MarkSweep::follow_root(T* p) { assert(!Universe::heap()->is_in(p), "roots shouldn't be things within the heap"); T heap_oop = RawAccess<>::oop_load(p); @@ -173,6 +173,41 @@ void MarkSweep::set_ref_processor(ReferenceProcessor* rp) { mark_and_push_closure.set_ref_discoverer(_ref_processor); } +void MarkSweep::mark_object(oop obj) { + if (StringDedup::is_enabled() && + java_lang_String::is_instance(obj) && + SerialStringDedup::is_candidate_from_mark(obj)) { + _string_dedup_requests->add(obj); + } + + // some marks may contain information we need to preserve so we store them away + // and overwrite the mark. We'll restore it at the end of markSweep. + markWord mark = obj->mark(); + obj->set_mark(markWord::prototype().set_marked()); + + ContinuationGCSupport::transform_stack_chunk(obj); + + if (obj->mark_must_be_preserved(mark)) { + preserve_mark(obj, mark); + } +} + +template void MarkSweep::mark_and_push(T* p) { + T heap_oop = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(heap_oop)) { + oop obj = CompressedOops::decode_not_null(heap_oop); + if (!obj->mark().is_marked()) { + mark_object(obj); + _marking_stack.push(obj); + } + } +} + +template +void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); } +void MarkAndPushClosure::do_oop( oop* p) { do_oop_work(p); } +void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } + AdjustPointerClosure MarkSweep::adjust_pointer_closure; void MarkSweep::adjust_marks() { diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp index 17e4692ce73..3c6a29e6902 100644 --- a/src/hotspot/share/gc/serial/markSweep.hpp +++ b/src/hotspot/share/gc/serial/markSweep.hpp @@ -38,8 +38,6 @@ class ReferenceProcessor; class DataLayout; -class Method; -class nmethod; class SerialOldTracer; class STWGCTimer; @@ -150,10 +148,6 @@ class MarkSweep : AllStatic { static void follow_stack(); // Empty marking stack. - static void follow_klass(Klass* klass); - - static void follow_cld(ClassLoaderData* cld); - template static inline void adjust_pointer(T* p); // Check mark and maybe push on marking stack @@ -174,18 +168,14 @@ class MarkSweep : AllStatic { static void follow_array_chunk(objArrayOop array, int index); }; -class MarkAndPushClosure: public OopIterateClosure { +class MarkAndPushClosure: public ClaimMetadataVisitingOopIterateClosure { public: + MarkAndPushClosure(int claim) : ClaimMetadataVisitingOopIterateClosure(claim) {} + template void do_oop_work(T* p); - virtual void do_oop(oop* p); + virtual void do_oop( oop* p); virtual void do_oop(narrowOop* p); - virtual bool do_metadata() { return true; } - virtual void do_klass(Klass* k); - virtual void do_cld(ClassLoaderData* cld); - virtual void do_method(Method* m); - virtual void do_nmethod(nmethod* nm); - void set_ref_discoverer(ReferenceDiscoverer* rd) { set_ref_discoverer_internal(rd); } diff --git a/src/hotspot/share/gc/serial/markSweep.inline.hpp b/src/hotspot/share/gc/serial/markSweep.inline.hpp index 71a61c7263b..97283e98746 100644 --- a/src/hotspot/share/gc/serial/markSweep.inline.hpp +++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp @@ -29,66 +29,16 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.inline.hpp" -#include "code/nmethod.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" #include "gc/serial/serialStringDedup.hpp" #include "memory/universe.hpp" #include "oops/markWord.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" -#include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "utilities/align.hpp" #include "utilities/stack.inline.hpp" -inline void MarkSweep::mark_object(oop obj) { - if (StringDedup::is_enabled() && - java_lang_String::is_instance(obj) && - SerialStringDedup::is_candidate_from_mark(obj)) { - _string_dedup_requests->add(obj); - } - - // some marks may contain information we need to preserve so we store them away - // and overwrite the mark. We'll restore it at the end of markSweep. - markWord mark = obj->mark(); - obj->set_mark(markWord::prototype().set_marked()); - - ContinuationGCSupport::transform_stack_chunk(obj); - - if (obj->mark_must_be_preserved(mark)) { - preserve_mark(obj, mark); - } -} - -template inline void MarkSweep::mark_and_push(T* p) { - T heap_oop = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(heap_oop)) { - oop obj = CompressedOops::decode_not_null(heap_oop); - if (!obj->mark().is_marked()) { - mark_object(obj); - _marking_stack.push(obj); - } - } -} - -inline void MarkSweep::follow_klass(Klass* klass) { - oop op = klass->class_loader_data()->holder_no_keepalive(); - MarkSweep::mark_and_push(&op); -} - -inline void MarkSweep::follow_cld(ClassLoaderData* cld) { - MarkSweep::follow_cld_closure.do_cld(cld); -} - -template -inline void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); } -inline void MarkAndPushClosure::do_oop(oop* p) { do_oop_work(p); } -inline void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } -inline void MarkAndPushClosure::do_klass(Klass* k) { MarkSweep::follow_klass(k); } -inline void MarkAndPushClosure::do_cld(ClassLoaderData* cld) { MarkSweep::follow_cld(cld); } -inline void MarkAndPushClosure::do_method(Method* m) { m->record_gc_epoch(); } -inline void MarkAndPushClosure::do_nmethod(nmethod* nm) { nm->follow_nmethod(this); } - template inline void MarkSweep::adjust_pointer(T* p) { T heap_oop = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(heap_oop)) { @@ -108,7 +58,6 @@ void AdjustPointerClosure::do_oop_work(T* p) { MarkSweep::adjust_point inline void AdjustPointerClosure::do_oop(oop* p) { do_oop_work(p); } inline void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_work(p); } - inline size_t MarkSweep::adjust_pointers(oop obj) { return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure); } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 522223981cd..47ff2d15900 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -486,7 +486,7 @@ void TenuredGeneration::object_iterate(ObjectClosure* blk) { void TenuredGeneration::complete_loaded_archive_space(MemRegion archive_space) { // Create the BOT for the archive space. - TenuredSpace* space = (TenuredSpace*)_the_space; + TenuredSpace* space = _the_space; space->initialize_threshold(); HeapWord* start = archive_space.start(); while (start < archive_space.end()) { diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 6f364a38f44..f897c00581e 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -65,13 +65,13 @@ class TenuredGeneration: public Generation { void assert_correct_size_change_locking(); - ContiguousSpace* _the_space; // Actual space holding objects + TenuredSpace* _the_space; // Actual space holding objects GenerationCounters* _gen_counters; CSpaceCounters* _space_counters; // Accessing spaces - ContiguousSpace* space() const { return _the_space; } + TenuredSpace* space() const { return _the_space; } // Attempt to expand the generation by "bytes". Expand by at a // minimum "expand_bytes". Return true if some amount (not diff --git a/src/hotspot/share/gc/serial/vmStructs_serial.hpp b/src/hotspot/share/gc/serial/vmStructs_serial.hpp index 30bd21d40a4..c8d43301f1c 100644 --- a/src/hotspot/share/gc/serial/vmStructs_serial.hpp +++ b/src/hotspot/share/gc/serial/vmStructs_serial.hpp @@ -37,7 +37,7 @@ nonstatic_field(TenuredGeneration, _capacity_at_prologue, size_t) \ nonstatic_field(TenuredGeneration, _used_at_prologue, size_t) \ nonstatic_field(TenuredGeneration, _min_heap_delta_bytes, size_t) \ - nonstatic_field(TenuredGeneration, _the_space, ContiguousSpace*) \ + nonstatic_field(TenuredGeneration, _the_space, TenuredSpace*) \ \ nonstatic_field(DefNewGeneration, _old_gen, Generation*) \ nonstatic_field(DefNewGeneration, _tenuring_threshold, uint) \ @@ -59,15 +59,14 @@ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_threshold, HeapWord*) \ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_index, size_t) \ \ - nonstatic_field(OffsetTableContigSpace, _offsets, BlockOffsetArray) + nonstatic_field(TenuredSpace, _offsets, BlockOffsetArray) #define VM_TYPES_SERIALGC(declare_type, \ declare_toplevel_type, \ declare_integer_type) \ declare_type(SerialHeap, GenCollectedHeap) \ declare_type(TenuredGeneration, Generation) \ - declare_type(TenuredSpace, OffsetTableContigSpace) \ - declare_type(OffsetTableContigSpace, ContiguousSpace) \ + declare_type(TenuredSpace, ContiguousSpace) \ \ declare_type(DefNewGeneration, Generation) \ \ @@ -76,8 +75,7 @@ declare_toplevel_type(BlockOffsetTable) \ declare_type(BlockOffsetArray, BlockOffsetTable) \ declare_type(BlockOffsetArrayContigSpace, BlockOffsetArray) \ - declare_toplevel_type(BlockOffsetSharedArray*) \ - declare_toplevel_type(OffsetTableContigSpace*) + declare_toplevel_type(BlockOffsetSharedArray*) #define VM_INT_CONSTANTS_SERIALGC(declare_constant, \ declare_constant_with_value) diff --git a/src/hotspot/share/gc/shared/barrierSet.cpp b/src/hotspot/share/gc/shared/barrierSet.cpp index 38609360222..933d6449e23 100644 --- a/src/hotspot/share/gc/shared/barrierSet.cpp +++ b/src/hotspot/share/gc/shared/barrierSet.cpp @@ -59,7 +59,7 @@ static BarrierSetNMethod* select_barrier_set_nmethod(BarrierSetNMethod* barrier_ } else { // The GC needs nmethod entry barriers to deal with continuations // and code cache unloading - return NOT_ARM32(new BarrierSetNMethod()) ARM32_ONLY(nullptr); + return new BarrierSetNMethod(); } } @@ -88,7 +88,7 @@ BarrierSet::BarrierSet(BarrierSetAssembler* barrier_set_assembler, void BarrierSet::on_thread_attach(Thread* thread) { BarrierSetNMethod* bs_nm = barrier_set_nmethod(); if (bs_nm != nullptr) { - thread->set_nmethod_disarm_value(bs_nm->disarmed_value()); + thread->set_nmethod_disarmed_guard_value(bs_nm->disarmed_guard_value()); } } diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp index 19c8c3bd86d..2f80028bd27 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -40,8 +40,8 @@ #include "runtime/threads.hpp" #include "utilities/debug.hpp" -int BarrierSetNMethod::disarmed_value() const { - return *disarmed_value_address(); +int BarrierSetNMethod::disarmed_guard_value() const { + return *disarmed_guard_value_address(); } bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) { @@ -69,6 +69,14 @@ bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) { return true; } +void BarrierSetNMethod::disarm(nmethod* nm) { + set_guard_value(nm, disarmed_guard_value()); +} + +bool BarrierSetNMethod::is_armed(nmethod* nm) { + return guard_value(nm) != disarmed_guard_value(); +} + bool BarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { class OopKeepAliveClosure : public OopClosure { public: @@ -102,24 +110,24 @@ bool BarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { return true; } -int* BarrierSetNMethod::disarmed_value_address() const { +int* BarrierSetNMethod::disarmed_guard_value_address() const { return (int*) &_current_phase; } -ByteSize BarrierSetNMethod::thread_disarmed_offset() const { - return Thread::nmethod_disarmed_offset(); +ByteSize BarrierSetNMethod::thread_disarmed_guard_value_offset() const { + return Thread::nmethod_disarmed_guard_value_offset(); } class BarrierSetNMethodArmClosure : public ThreadClosure { private: - int _disarm_value; + int _disarmed_guard_value; public: - BarrierSetNMethodArmClosure(int disarm_value) : - _disarm_value(disarm_value) {} + BarrierSetNMethodArmClosure(int disarmed_guard_value) : + _disarmed_guard_value(disarmed_guard_value) {} virtual void do_thread(Thread* thread) { - thread->set_nmethod_disarm_value(_disarm_value); + thread->set_nmethod_disarmed_guard_value(_disarmed_guard_value); } }; diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp index 81099d66fea..7629c11949a 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp @@ -41,16 +41,18 @@ class BarrierSetNMethod: public CHeapObj { bool supports_entry_barrier(nmethod* nm); virtual bool nmethod_entry_barrier(nmethod* nm); - virtual ByteSize thread_disarmed_offset() const; - virtual int* disarmed_value_address() const; + virtual ByteSize thread_disarmed_guard_value_offset() const; + virtual int* disarmed_guard_value_address() const; - int disarmed_value() const; + int disarmed_guard_value() const; static int nmethod_stub_entry_barrier(address* return_address_ptr); bool nmethod_osr_entry_barrier(nmethod* nm); bool is_armed(nmethod* nm); void disarm(nmethod* nm); - void arm(nmethod* nm, int arm_value); + + int guard_value(nmethod* nm); + void set_guard_value(nmethod* nm, int value); void arm_all_nmethods(); }; diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp index 777d68ff872..bc0a9a7e57b 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp @@ -76,7 +76,7 @@ class LIRAccess: public StackObj { LIRAddressOpr base, LIRAddressOpr offset, BasicType type, CodeEmitInfo* patch_emit_info = NULL, CodeEmitInfo* access_emit_info = NULL) : _gen(gen), - _decorators(AccessInternal::decorator_fixup(decorators)), + _decorators(AccessInternal::decorator_fixup(decorators, type)), _base(base), _offset(offset), _type(type), diff --git a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp index 660c324aa99..21b1ef7ea7e 100644 --- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -66,7 +66,7 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Op gen->CardTableBarrierSet_post_barrier_helper(addr, card_table_base); #else LIR_Opr tmp = gen->new_pointer_register(); - if (TwoOperandLIRForm) { + if (two_operand_lir_form) { LIR_Opr addr_opr = LIR_OprFact::address(new LIR_Address(addr, addr->type())); __ leal(addr_opr, tmp); __ unsigned_shift_right(tmp, CardTable::card_shift(), tmp); diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index c518ad4216a..f41cd0e2ac3 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -358,7 +358,7 @@ void C2Access::fixup_decorators() { _decorators |= MO_RELAXED; // Force the MO_RELAXED decorator with AlwaysAtomicAccess } - _decorators = AccessInternal::decorator_fixup(_decorators); + _decorators = AccessInternal::decorator_fixup(_decorators, _type); if (is_read && !is_write && anonymous) { // To be valid, unsafe loads may depend on other conditions than diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp index 6238ae3234c..5c86dcc0c82 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -264,6 +264,7 @@ class BarrierSetC2: public CHeapObj { virtual void register_potential_barrier_node(Node* node) const { } virtual void unregister_potential_barrier_node(Node* node) const { } virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, 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 {} diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index 3e47b1d28a1..89a21a8e5bf 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -113,17 +113,6 @@ class CardTable: public CHeapObj { virtual ~CardTable(); virtual void initialize(); - // The kinds of precision a CardTable may offer. - enum PrecisionStyle { - Precise, - ObjHeadPreciseArray - }; - - // Tells what style of precision this card table offers. - PrecisionStyle precision() { - return ObjHeadPreciseArray; // Only one supported for now. - } - // *** Barrier set functions. // Initialization utilities; covered_words is the size of the covered region diff --git a/src/hotspot/share/gc/shared/cardTableRS.cpp b/src/hotspot/share/gc/shared/cardTableRS.cpp index bff99c179e0..c547c2960bc 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.cpp +++ b/src/hotspot/share/gc/shared/cardTableRS.cpp @@ -111,7 +111,7 @@ void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) { } } -void CardTableRS::younger_refs_in_space_iterate(Space* sp, +void CardTableRS::younger_refs_in_space_iterate(TenuredSpace* sp, HeapWord* gen_boundary, OopIterateClosure* cl) { verify_used_region_at_save_marks(sp); @@ -440,7 +440,7 @@ void CardTableRS::initialize() { CardTable::initialize(); } -void CardTableRS::non_clean_card_iterate(Space* sp, +void CardTableRS::non_clean_card_iterate(TenuredSpace* sp, HeapWord* gen_boundary, MemRegion mr, OopIterateClosure* cl, @@ -451,7 +451,7 @@ void CardTableRS::non_clean_card_iterate(Space* sp, } // clear_cl finds contiguous dirty ranges of cards to process and clear. - DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), gen_boundary); + DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, gen_boundary); ClearNoncleanCardWrapper clear_cl(dcto_cl, ct); clear_cl.do_MemRegion(mr); diff --git a/src/hotspot/share/gc/shared/cardTableRS.hpp b/src/hotspot/share/gc/shared/cardTableRS.hpp index 4a7135c02b7..41c634fbe26 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.hpp +++ b/src/hotspot/share/gc/shared/cardTableRS.hpp @@ -32,6 +32,7 @@ class DirtyCardToOopClosure; class Generation; class Space; +class TenuredSpace; // This RemSet uses a card table both as shared data structure // for a mod ref barrier set and for the rem set information. @@ -47,7 +48,7 @@ class CardTableRS : public CardTable { public: CardTableRS(MemRegion whole_heap); - void younger_refs_in_space_iterate(Space* sp, HeapWord* gen_boundary, OopIterateClosure* cl); + void younger_refs_in_space_iterate(TenuredSpace* sp, HeapWord* gen_boundary, OopIterateClosure* cl); virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN; @@ -70,7 +71,7 @@ class CardTableRS : public CardTable { // Iterate over the portion of the card-table which covers the given // region mr in the given space and apply cl to any dirty sub-regions // of mr. Clears the dirty cards as they are processed. - void non_clean_card_iterate(Space* sp, + void non_clean_card_iterate(TenuredSpace* sp, HeapWord* gen_boundary, MemRegion mr, OopIterateClosure* cl, diff --git a/src/hotspot/share/gc/shared/gcBehaviours.cpp b/src/hotspot/share/gc/shared/gcBehaviours.cpp index d0a4eb79a40..3b5136f74f0 100644 --- a/src/hotspot/share/gc/shared/gcBehaviours.cpp +++ b/src/hotspot/share/gc/shared/gcBehaviours.cpp @@ -30,6 +30,11 @@ IsUnloadingBehaviour* IsUnloadingBehaviour::_current = NULL; bool IsUnloadingBehaviour::is_unloading(CompiledMethod* cm) { + if (cm->method()->can_be_allocated_in_NonNMethod_space()) { + // When the nmethod is in NonNMethod space, we may reach here without IsUnloadingBehaviour. + // However, we only allow this for special methods which never get unloaded. + return false; + } return _current->has_dead_oop(cm) || cm->as_nmethod()->is_cold(); } diff --git a/src/hotspot/share/gc/shared/gcCause.cpp b/src/hotspot/share/gc/shared/gcCause.cpp index 37cd32b0ff2..dc5a83d5d00 100644 --- a/src/hotspot/share/gc/shared/gcCause.cpp +++ b/src/hotspot/share/gc/shared/gcCause.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,9 +54,6 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _wb_young_gc: return "WhiteBox Initiated Young GC"; - case _wb_conc_mark: - return "WhiteBox Initiated Concurrent Mark"; - case _wb_full_gc: return "WhiteBox Initiated Full GC"; @@ -99,9 +96,6 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _g1_periodic_collection: return "G1 Periodic Collection"; - case _g1_preventive_collection: - return "G1 Preventive Collection"; - case _dcmd_gc_run: return "Diagnostic Command"; diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index 1def51523d6..0b3225c524e 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -51,7 +51,6 @@ class GCCause : public AllStatic { _heap_inspection, _heap_dump, _wb_young_gc, - _wb_conc_mark, _wb_full_gc, _wb_breakpoint, _archive_time_gc, @@ -74,7 +73,6 @@ class GCCause : public AllStatic { _g1_compaction_pause, _g1_humongous_allocation, _g1_periodic_collection, - _g1_preventive_collection, _dcmd_gc_run, diff --git a/src/hotspot/share/gc/shared/gcHeapSummary.hpp b/src/hotspot/share/gc/shared/gcHeapSummary.hpp index c0ed793fb67..6f72ec51b60 100644 --- a/src/hotspot/share/gc/shared/gcHeapSummary.hpp +++ b/src/hotspot/share/gc/shared/gcHeapSummary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -117,13 +117,15 @@ class G1HeapSummary : public GCHeapSummary { size_t _edenUsed; size_t _edenCapacity; size_t _survivorUsed; + size_t _oldGenUsed; uint _numberOfRegions; public: - G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, uint numberOfRegions) : - GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _numberOfRegions(numberOfRegions) { } + G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, size_t oldGenUsed, uint numberOfRegions) : + GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _oldGenUsed(oldGenUsed), _numberOfRegions(numberOfRegions) { } const size_t edenUsed() const { return _edenUsed; } const size_t edenCapacity() const { return _edenCapacity; } const size_t survivorUsed() const { return _survivorUsed; } + const size_t oldGenUsed() const { return _oldGenUsed; } const uint numberOfRegions() const { return _numberOfRegions; } virtual void accept(GCHeapSummaryVisitor* visitor) const { diff --git a/src/hotspot/share/gc/shared/gcTraceSend.cpp b/src/hotspot/share/gc/shared/gcTraceSend.cpp index 5ee37592f28..d7117ffbb40 100644 --- a/src/hotspot/share/gc/shared/gcTraceSend.cpp +++ b/src/hotspot/share/gc/shared/gcTraceSend.cpp @@ -244,6 +244,7 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { e.set_edenUsedSize(g1_heap_summary->edenUsed()); e.set_edenTotalSize(g1_heap_summary->edenCapacity()); e.set_survivorUsedSize(g1_heap_summary->survivorUsed()); + e.set_oldGenUsedSize(g1_heap_summary->oldGenUsed()); e.set_numberOfRegions(g1_heap_summary->numberOfRegions()); e.commit(); } @@ -389,6 +390,7 @@ void GCLockerTracer::report_gc_locker() { EventGCLocker event(UNTIMED); if (event.should_commit()) { event.set_starttime(_needs_gc_start_timestamp); + event.set_endtime(_needs_gc_start_timestamp); event.set_lockCount(_jni_lock_count); event.set_stallCount(_stall_count); event.commit(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 104ddb6fa28..9ae88825819 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -793,20 +793,6 @@ void GenCollectedHeap::process_roots(ScanningOption so, DEBUG_ONLY(ScavengableNMethods::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); } -void GenCollectedHeap::full_process_roots(bool is_adjust_phase, - ScanningOption so, - bool only_strong_roots, - OopClosure* root_closure, - CLDClosure* cld_closure) { - // Called from either the marking phase or the adjust phase. - const bool is_marking_phase = !is_adjust_phase; - - MarkingCodeBlobClosure mark_code_closure(root_closure, is_adjust_phase, is_marking_phase); - CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; - - process_roots(so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure); -} - void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) { WeakProcessor::oops_do(root_closure); } diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 860e2e0abd5..c688cfa27d7 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -326,22 +326,17 @@ class GenCollectedHeap : public CollectedHeap { }; protected: + virtual void gc_prologue(bool full); + virtual void gc_epilogue(bool full); + + public: + // Apply closures on various roots in Young GC or marking/adjust phases of Full GC. void process_roots(ScanningOption so, OopClosure* strong_roots, CLDClosure* strong_cld_closure, CLDClosure* weak_cld_closure, CodeBlobToOopClosure* code_roots); - virtual void gc_prologue(bool full); - virtual void gc_epilogue(bool full); - - public: - void full_process_roots(bool is_adjust_phase, - ScanningOption so, - bool only_strong_roots, - OopClosure* root_closure, - CLDClosure* cld_closure); - // Apply "root_closure" to all the weak roots of the system. // These include JNI weak roots, string table, // and referents of reachable weak refs. diff --git a/src/hotspot/share/gc/shared/genOopClosures.hpp b/src/hotspot/share/gc/shared/genOopClosures.hpp index 05601199118..4ba6e82aa30 100644 --- a/src/hotspot/share/gc/shared/genOopClosures.hpp +++ b/src/hotspot/share/gc/shared/genOopClosures.hpp @@ -32,7 +32,6 @@ class Generation; class CardTableRS; class CardTableBarrierSet; class DefNewGeneration; -class KlassRemSet; class Method; class nmethod; diff --git a/src/hotspot/share/gc/shared/objectCountEventSender.cpp b/src/hotspot/share/gc/shared/objectCountEventSender.cpp index bf24a98cf67..ce78b847708 100644 --- a/src/hotspot/share/gc/shared/objectCountEventSender.cpp +++ b/src/hotspot/share/gc/shared/objectCountEventSender.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -54,11 +54,12 @@ template void ObjectCountEventSender::send_event_if_enabled(Klass* klass, jlong count, julong size, const Ticks& timestamp) { T event(UNTIMED); if (event.should_commit()) { + event.set_starttime(timestamp); + event.set_endtime(timestamp); event.set_gcId(GCId::current()); event.set_objectClass(klass); event.set_count(count); event.set_totalSize(size); - event.set_endtime(timestamp); event.commit(); } } diff --git a/src/hotspot/share/gc/shared/oopStorage.inline.hpp b/src/hotspot/share/gc/shared/oopStorage.inline.hpp index 4bcff174b5f..45dfe1cde8c 100644 --- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp +++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "metaprogramming/conditional.hpp" -#include "metaprogramming/isConst.hpp" #include "oops/oop.hpp" #include "runtime/safepoint.hpp" #include "utilities/align.hpp" @@ -37,6 +36,8 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include + // Array of all active blocks. Refcounted for lock-free reclaim of // old array when a new array is allocated for expansion. class OopStorage::ActiveArray { @@ -361,7 +362,7 @@ inline bool OopStorage::iterate_impl(F f, Storage* storage) { assert_at_safepoint(); // Propagate const/non-const iteration to the block layer, by using // const or non-const blocks as corresponding to Storage. - typedef typename Conditional::value, const Block*, Block*>::type BlockPtr; + typedef typename Conditional::value, const Block*, Block*>::type BlockPtr; ActiveArray* blocks = storage->_active_array; size_t limit = blocks->block_count(); for (size_t i = 0; i < limit; ++i) { diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 894c3d91cd9..f6666858b5f 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -282,7 +282,7 @@ void DiscoveredListIterator::make_referent_alive() { } void DiscoveredListIterator::clear_referent() { - java_lang_ref_Reference::clear_referent(_current_discovered); + java_lang_ref_Reference::clear_referent_raw(_current_discovered); } void DiscoveredListIterator::enqueue() { diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 84925eb499d..b77f6f6c1b3 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -51,20 +51,14 @@ HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL) { if (_sp->block_is_obj(top_obj)) { - if (_precision == CardTable::ObjHeadPreciseArray) { - if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) { - // An arrayOop is starting on the dirty card - since we do exact - // store checks for objArrays we are done. - } else { - // Otherwise, it is possible that the object starting on the dirty - // card spans the entire card, and that the store happened on a - // later card. Figure out where the object ends. - // Use the block_size() method of the space over which - // the iteration is being done. That space (e.g. CMS) may have - // specific requirements on object sizes which will - // be reflected in the block_size() method. - top = top_obj + cast_to_oop(top_obj)->size(); - } + if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) { + // An arrayOop is starting on the dirty card - since we do exact + // store checks for objArrays we are done. + } else { + // Otherwise, it is possible that the object starting on the dirty + // card spans the entire card, and that the store happened on a + // later card. Figure out where the object ends. + top = top_obj + cast_to_oop(top_obj)->size(); } } else { top = top_obj; @@ -115,12 +109,7 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { HeapWord* bottom_obj; HeapWord* top_obj; - assert(_precision == CardTable::ObjHeadPreciseArray || - _precision == CardTable::Precise, - "Only ones we deal with for now."); - - assert(_precision != CardTable::ObjHeadPreciseArray || - _last_bottom == NULL || top <= _last_bottom, + assert(_last_bottom == NULL || top <= _last_bottom, "Not decreasing"); NOT_PRODUCT(_last_bottom = mr.start()); @@ -136,9 +125,7 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { top = get_actual_top(top, top_obj); // If the previous call did some part of this region, don't redo. - if (_precision == CardTable::ObjHeadPreciseArray && - _min_done != NULL && - _min_done < top) { + if (_min_done != NULL && _min_done < top) { top = _min_done; } @@ -148,9 +135,7 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { bottom = MIN2(bottom, top); MemRegion extended_mr = MemRegion(bottom, top); assert(bottom <= top && - (_precision != CardTable::ObjHeadPreciseArray || - _min_done == NULL || - top <= _min_done), + (_min_done == NULL || top <= _min_done), "overlap!"); // Walk the region if it is not empty; otherwise there is nothing to do. @@ -161,27 +146,19 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { _min_done = bottom; } -DirtyCardToOopClosure* Space::new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, - HeapWord* boundary) { - return new DirtyCardToOopClosure(this, cl, precision, boundary); -} - HeapWord* ContiguousSpaceDCTOC::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL && top_obj < (_sp->toContiguousSpace())->top()) { - if (_precision == CardTable::ObjHeadPreciseArray) { - if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) { - // An arrayOop is starting on the dirty card - since we do exact - // store checks for objArrays we are done. - } else { - // Otherwise, it is possible that the object starting on the dirty - // card spans the entire card, and that the store happened on a - // later card. Figure out where the object ends. - assert(_sp->block_size(top_obj) == cast_to_oop(top_obj)->size(), - "Block size and object size mismatch"); - top = top_obj + cast_to_oop(top_obj)->size(); - } + if (cast_to_oop(top_obj)->is_objArray() || cast_to_oop(top_obj)->is_typeArray()) { + // An arrayOop is starting on the dirty card - since we do exact + // store checks for objArrays we are done. + } else { + // Otherwise, it is possible that the object starting on the dirty + // card spans the entire card, and that the store happened on a + // later card. Figure out where the object ends. + assert(_sp->block_size(top_obj) == cast_to_oop(top_obj)->size(), + "Block size and object size mismatch"); + top = top_obj + cast_to_oop(top_obj)->size(); } } else { top = (_sp->toContiguousSpace())->top(); @@ -241,9 +218,8 @@ ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) DirtyCardToOopClosure* ContiguousSpace::new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, HeapWord* boundary) { - return new ContiguousSpaceDCTOC(this, cl, precision, boundary); + return new ContiguousSpaceDCTOC(this, cl, boundary); } void Space::initialize(MemRegion mr, @@ -290,17 +266,17 @@ bool ContiguousSpace::is_free_block(const HeapWord* p) const { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::clear(bool mangle_space) { +void TenuredSpace::clear(bool mangle_space) { ContiguousSpace::clear(mangle_space); _offsets.initialize_threshold(); } -void OffsetTableContigSpace::set_bottom(HeapWord* new_bottom) { +void TenuredSpace::set_bottom(HeapWord* new_bottom) { Space::set_bottom(new_bottom); _offsets.set_bottom(new_bottom); } -void OffsetTableContigSpace::set_end(HeapWord* new_end) { +void TenuredSpace::set_end(HeapWord* new_end) { // Space should not advertise an increase in size // until after the underlying offset table has been enlarged. _offsets.resize(pointer_delta(new_end, bottom())); @@ -596,7 +572,7 @@ void ContiguousSpace::print_on(outputStream* st) const { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::print_on(outputStream* st) const { +void TenuredSpace::print_on(outputStream* st) const { print_short_on(st); st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")", @@ -739,18 +715,18 @@ HeapWord* ContiguousSpace::par_allocate(size_t size) { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::initialize_threshold() { +void TenuredSpace::initialize_threshold() { _offsets.initialize_threshold(); } -void OffsetTableContigSpace::alloc_block(HeapWord* start, HeapWord* end) { +void TenuredSpace::alloc_block(HeapWord* start, HeapWord* end) { _offsets.alloc_block(start, end); } -OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr) : +TenuredSpace::TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, + MemRegion mr) : _offsets(sharedOffsetArray, mr), - _par_alloc_lock(Mutex::safepoint, "OffsetTableContigSpaceParAlloc_lock", true) + _par_alloc_lock(Mutex::safepoint, "TenuredSpaceParAlloc_lock", true) { _offsets.set_contig_space(this); initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); @@ -759,7 +735,7 @@ OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOff #define OBJ_SAMPLE_INTERVAL 0 #define BLOCK_SAMPLE_INTERVAL 100 -void OffsetTableContigSpace::verify() const { +void TenuredSpace::verify() const { HeapWord* p = bottom(); HeapWord* prev_p = NULL; int objs = 0; diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 466d3ff5748..c9606e7fdbb 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -132,7 +132,6 @@ class Space: public CHeapObj { // Testers bool is_empty() const { return used() == 0; } - bool not_empty() const { return used() > 0; } // Returns true iff the given the space contains the // given address as part of an allocated object. For @@ -174,14 +173,6 @@ class Space: public CHeapObj { // included in the iteration. virtual void object_iterate(ObjectClosure* blk) = 0; - // Create and return a new dirty card to oop closure. Can be - // overridden to return the appropriate type of closure - // depending on the type of space in which the closure will - // operate. ResourceArea allocated. - virtual DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, - HeapWord* boundary); - // If "p" is in the space, returns the address of the start of the // "block" that contains "p". We say "block" instead of "object" since // some heaps may not pack objects densely; a chunk may either be an @@ -249,16 +240,14 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { protected: OopIterateClosure* _cl; Space* _sp; - CardTable::PrecisionStyle _precision; HeapWord* _boundary; // If non-NULL, process only non-NULL oops // pointing below boundary. - HeapWord* _min_done; // ObjHeadPreciseArray precision requires - // a downwards traversal; this is the + HeapWord* _min_done; // Need a downwards traversal to compensate + // imprecise write barrier; this is the // lowest location already done (or, // alternatively, the lowest address that // shouldn't be done again. NULL means infinity.) NOT_PRODUCT(HeapWord* _last_bottom;) - NOT_PRODUCT(HeapWord* _last_explicit_min_done;) // Get the actual top of the area on which the closure will // operate, given where the top is assumed to be (the end of the @@ -278,25 +267,13 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { public: DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl, - CardTable::PrecisionStyle precision, HeapWord* boundary) : - _cl(cl), _sp(sp), _precision(precision), _boundary(boundary), + _cl(cl), _sp(sp), _boundary(boundary), _min_done(NULL) { NOT_PRODUCT(_last_bottom = NULL); - NOT_PRODUCT(_last_explicit_min_done = NULL); } - void do_MemRegion(MemRegion mr); - - void set_min_done(HeapWord* min_done) { - _min_done = min_done; - NOT_PRODUCT(_last_explicit_min_done = _min_done); - } -#ifndef PRODUCT - void set_last_bottom(HeapWord* last_bottom) { - _last_bottom = last_bottom; - } -#endif + void do_MemRegion(MemRegion mr) override; }; // A structure to represent a point at which objects are being copied @@ -330,8 +307,8 @@ class CompactibleSpace: public Space { CompactibleSpace() : _compaction_top(NULL), _next_compaction_space(NULL) {} - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); - virtual void clear(bool mangle_space); + void initialize(MemRegion mr, bool clear_space, bool mangle_space) override; + void clear(bool mangle_space) override; // Used temporarily during a compaction phase to hold the value // top should have when compaction is complete. @@ -372,7 +349,7 @@ class CompactibleSpace: public Space { // indicates when the next such action should be taken. virtual void prepare_for_compaction(CompactPoint* cp) = 0; // MarkSweep support phase3 - virtual void adjust_pointers(); + void adjust_pointers() override; // MarkSweep support phase4 virtual void compact(); #endif // INCLUDE_SERIALGC @@ -399,13 +376,6 @@ class CompactibleSpace: public Space { // space. virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); - - // Return a size with adjustments as required of the space. - virtual size_t adjust_object_size_v(size_t size) const { return size; } - - void set_first_dead(HeapWord* value) { _first_dead = value; } - void set_end_of_live(HeapWord* value) { _end_of_live = value; } - protected: // Used during compaction. HeapWord* _first_dead; @@ -438,8 +408,8 @@ class ContiguousSpace: public CompactibleSpace { ContiguousSpace(); ~ContiguousSpace(); - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); - virtual void clear(bool mangle_space); + void initialize(MemRegion mr, bool clear_space, bool mangle_space) override; + void clear(bool mangle_space) override; // Accessors HeapWord* top() const { return _top; } @@ -460,9 +430,9 @@ class ContiguousSpace: public CompactibleSpace { // Mangle regions in the space from the current top up to the // previously mangled part of the space. - void mangle_unused_area() PRODUCT_RETURN; + void mangle_unused_area() override PRODUCT_RETURN; // Mangle [top, end) - void mangle_unused_area_complete() PRODUCT_RETURN; + void mangle_unused_area_complete() override PRODUCT_RETURN; // Do some sparse checking on the area that should have been mangled. void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; @@ -471,33 +441,30 @@ class ContiguousSpace: public CompactibleSpace { void check_mangled_unused_area_complete() PRODUCT_RETURN; // Size computations: sizes in bytes. - size_t capacity() const { return byte_size(bottom(), end()); } - size_t used() const { return byte_size(bottom(), top()); } - size_t free() const { return byte_size(top(), end()); } + size_t used() const override { return byte_size(bottom(), top()); } + size_t free() const override { return byte_size(top(), end()); } - virtual bool is_free_block(const HeapWord* p) const; + bool is_free_block(const HeapWord* p) const override; // In a contiguous space we have a more obvious bound on what parts // contain objects. - MemRegion used_region() const { return MemRegion(bottom(), top()); } + MemRegion used_region() const override { return MemRegion(bottom(), top()); } // Allocation (return NULL if full) - virtual HeapWord* allocate(size_t word_size); - virtual HeapWord* par_allocate(size_t word_size); + HeapWord* allocate(size_t word_size) override; + HeapWord* par_allocate(size_t word_size) override; // Iteration - void oop_iterate(OopIterateClosure* cl); - void object_iterate(ObjectClosure* blk); + void oop_iterate(OopIterateClosure* cl) override; + void object_iterate(ObjectClosure* blk) override; // Compaction support - virtual void reset_after_compaction() { + void reset_after_compaction() override { assert(compaction_top() >= bottom() && compaction_top() <= end(), "should point inside space"); set_top(compaction_top()); } - // Override. DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, HeapWord* boundary); // Apply "blk->do_oop" to the addresses of all reference fields in objects @@ -516,10 +483,10 @@ class ContiguousSpace: public CompactibleSpace { virtual void object_iterate_from(HeapWord* mark, ObjectClosure* blk); // Very inefficient implementation. - virtual HeapWord* block_start_const(const void* p) const; - size_t block_size(const HeapWord* p) const; + HeapWord* block_start_const(const void* p) const override; + size_t block_size(const HeapWord* p) const override; // If a block is in the allocated area, it is an object. - bool block_is_obj(const HeapWord* p) const { return p < top(); } + bool block_is_obj(const HeapWord* p) const override { return p < top(); } // Addresses for inlined allocation HeapWord** top_addr() { return &_top; } @@ -527,18 +494,18 @@ class ContiguousSpace: public CompactibleSpace { #if INCLUDE_SERIALGC // Overrides for more efficient compaction support. - void prepare_for_compaction(CompactPoint* cp); + void prepare_for_compaction(CompactPoint* cp) override; #endif - virtual void print_on(outputStream* st) const; + void print_on(outputStream* st) const override; // Checked dynamic downcasts. - virtual ContiguousSpace* toContiguousSpace() { + ContiguousSpace* toContiguousSpace() override { return this; } // Debugging - virtual void verify() const; + void verify() const override; }; // A dirty card to oop closure for contiguous spaces (ContiguousSpace and @@ -554,9 +521,9 @@ class ContiguousSpace: public CompactibleSpace { class ContiguousSpaceDCTOC : public DirtyCardToOopClosure { // Overrides. void walk_mem_region(MemRegion mr, - HeapWord* bottom, HeapWord* top); + HeapWord* bottom, HeapWord* top) override; - HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj); + HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj) override; // Walk the given memory region, from bottom to top, applying // the given oop closure to (possibly) all objects found. The @@ -574,63 +541,50 @@ class ContiguousSpaceDCTOC : public DirtyCardToOopClosure { public: ContiguousSpaceDCTOC(ContiguousSpace* sp, OopIterateClosure* cl, - CardTable::PrecisionStyle precision, HeapWord* boundary) : - DirtyCardToOopClosure(sp, cl, precision, boundary) + DirtyCardToOopClosure(sp, cl, boundary) {} }; -// A ContigSpace that Supports an efficient "block_start" operation via -// a BlockOffsetArray (whose BlockOffsetSharedArray may be shared with -// other spaces.) This is the abstract base class for old generation -// (tenured) spaces. #if INCLUDE_SERIALGC -class OffsetTableContigSpace: public ContiguousSpace { + +// Class TenuredSpace is used by TenuredGeneration; it supports an efficient +// "block_start" operation via a BlockOffsetArray (whose BlockOffsetSharedArray +// may be shared with other spaces.) + +class TenuredSpace: public ContiguousSpace { friend class VMStructs; protected: BlockOffsetArrayContigSpace _offsets; Mutex _par_alloc_lock; + // Mark sweep support + size_t allowed_dead_ratio() const override; public: // Constructor - OffsetTableContigSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr); + TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, + MemRegion mr); - void set_bottom(HeapWord* value); - void set_end(HeapWord* value); + void set_bottom(HeapWord* value) override; + void set_end(HeapWord* value) override; - void clear(bool mangle_space); + void clear(bool mangle_space) override; - inline HeapWord* block_start_const(const void* p) const; + inline HeapWord* block_start_const(const void* p) const override; // Add offset table update. - virtual inline HeapWord* allocate(size_t word_size); - inline HeapWord* par_allocate(size_t word_size); + inline HeapWord* allocate(size_t word_size) override; + inline HeapWord* par_allocate(size_t word_size) override; // MarkSweep support phase3 - virtual void initialize_threshold(); - virtual void alloc_block(HeapWord* start, HeapWord* end); + void initialize_threshold() override; + void alloc_block(HeapWord* start, HeapWord* end) override; - virtual void print_on(outputStream* st) const; + void print_on(outputStream* st) const override; // Debugging - void verify() const; -}; - - -// Class TenuredSpace is used by TenuredGeneration - -class TenuredSpace: public OffsetTableContigSpace { - friend class VMStructs; - protected: - // Mark sweep support - size_t allowed_dead_ratio() const; - public: - // Constructor - TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr) : - OffsetTableContigSpace(sharedOffsetArray, mr) {} + void verify() const override; }; #endif //INCLUDE_SERIALGC diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp index 963b9a2d9cb..a2b3b67ed57 100644 --- a/src/hotspot/share/gc/shared/space.inline.hpp +++ b/src/hotspot/share/gc/shared/space.inline.hpp @@ -44,7 +44,7 @@ inline HeapWord* Space::block_start(const void* p) { } #if INCLUDE_SERIALGC -inline HeapWord* OffsetTableContigSpace::allocate(size_t size) { +inline HeapWord* TenuredSpace::allocate(size_t size) { HeapWord* res = ContiguousSpace::allocate(size); if (res != NULL) { _offsets.alloc_block(res, size); @@ -55,7 +55,7 @@ inline HeapWord* OffsetTableContigSpace::allocate(size_t size) { // Because of the requirement of keeping "_offsets" up to date with the // allocations, we sequentialize these with a lock. Therefore, best if // this is used for larger LAB allocations only. -inline HeapWord* OffsetTableContigSpace::par_allocate(size_t size) { +inline HeapWord* TenuredSpace::par_allocate(size_t size) { MutexLocker x(&_par_alloc_lock); // This ought to be just "allocate", because of the lock above, but that // ContiguousSpace::allocate asserts that either the allocating thread @@ -73,7 +73,7 @@ inline HeapWord* OffsetTableContigSpace::par_allocate(size_t size) { } inline HeapWord* -OffsetTableContigSpace::block_start_const(const void* p) const { +TenuredSpace::block_start_const(const void* p) const { return _offsets.block_start(p); } @@ -156,7 +156,7 @@ inline void CompactibleSpace::clear_empty_region(SpaceType* space) { // Reset space after compaction is complete space->reset_after_compaction(); // We do this clear, below, since it has overloaded meanings for some - // space subtypes. For example, OffsetTableContigSpace's that were + // space subtypes. For example, TenuredSpace's that were // compacted into will have had their offset table thresholds updated // continuously, but those that weren't need to have their thresholds // re-initialized. Also mangles unused area for debugging. diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index dfa92cf61b5..1d0dff411d5 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -235,8 +235,6 @@ \ declare_constant(CardTable::clean_card) \ declare_constant(CardTable::dirty_card) \ - declare_constant(CardTable::Precise) \ - declare_constant(CardTable::ObjHeadPreciseArray) \ \ declare_constant(CollectedHeap::Serial) \ declare_constant(CollectedHeap::Parallel) \ diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index 97041ee1743..392f79037aa 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -146,7 +146,7 @@ LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, L LIR_Opr mask_reg = gen->new_register(T_INT); __ move(mask, mask_reg); - if (TwoOperandLIRForm) { + if (two_operand_lir_form) { __ logical_and(flag_val, mask_reg, flag_val); } else { LIR_Opr masked_flag = gen->new_register(T_INT); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 950e64dd688..c561389307e 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -1028,7 +1028,7 @@ void ShenandoahBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase p if (if_ctrl != load_ctrl) { // Skip possible CProj->NeverBranch in infinite loops if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) - && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { + && if_ctrl->in(0)->is_NeverBranch()) { if_ctrl = if_ctrl->in(0)->in(0); } } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index a1283726232..d443bb8aa33 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -757,7 +757,7 @@ Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one return NodeSentinel; // unsupported } else if (c->Opcode() == Op_CatchProj) { return NodeSentinel; // unsupported - } else if (c->Opcode() == Op_CProj && next->Opcode() == Op_NeverBranch) { + } else if (c->Opcode() == Op_CProj && next->is_NeverBranch()) { return NodeSentinel; // unsupported } else { assert(next->unique_ctrl_out() == c, "unsupported branch pattern"); @@ -2002,7 +2002,7 @@ Node* ShenandoahIUBarrierNode::Identity(PhaseGVN* phase) { static bool has_never_branch(Node* root) { for (uint i = 1; i < root->req(); i++) { Node* in = root->in(i); - if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->Opcode() == Op_NeverBranch) { + if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->is_NeverBranch()) { return true; } } @@ -2033,20 +2033,20 @@ void MemoryGraphFixer::collect_memory_nodes() { if (in->in(0)->is_Region()) { Node* r = in->in(0); for (uint j = 1; j < r->req(); j++) { - assert(r->in(j)->Opcode() != Op_NeverBranch, ""); + assert(!r->in(j)->is_NeverBranch(), ""); } } else { Node* proj = in->in(0); assert(proj->is_Proj(), ""); Node* in = proj->in(0); - assert(in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj(), ""); + assert(in->is_CallStaticJava() || in->is_NeverBranch() || in->Opcode() == Op_Catch || proj->is_IfProj(), ""); if (in->is_CallStaticJava()) { mem = in->in(TypeFunc::Memory); } else if (in->Opcode() == Op_Catch) { Node* call = in->in(0)->in(0); assert(call->is_Call(), ""); mem = call->in(TypeFunc::Memory); - } else if (in->Opcode() == Op_NeverBranch) { + } else if (in->is_NeverBranch()) { mem = collect_memory_for_infinite_loop(in); } } @@ -2518,7 +2518,7 @@ void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_ } } } else if (!mem_is_valid(m, u) && - !(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) { + !(u->Opcode() == Op_CProj && u->in(0)->is_NeverBranch() && u->as_Proj()->_con == 1)) { uses.push(u); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index be2067a0d81..ef58f91524b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -104,7 +104,7 @@ void ShenandoahBarrierSet::on_thread_attach(Thread *thread) { BarrierSetNMethod* bs_nm = barrier_set_nmethod(); if (bs_nm != NULL) { - thread->set_nmethod_disarm_value(bs_nm->disarmed_value()); + thread->set_nmethod_disarmed_guard_value(bs_nm->disarmed_guard_value()); } if (ShenandoahStackWatermarkBarrier) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp index 237e080a584..2c6675c292a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -210,7 +210,7 @@ class ShenandoahNMethodUnlinkClosure : public NMethodClosure { ShenandoahNMethod::heal_nmethod_metadata(nm_data); // Code cache unloading needs to know about on-stack nmethods. Arm the nmethods to get // mark_as_maybe_on_stack() callbacks when they are used again. - _bs->arm(nm, 0); + _bs->set_guard_value(nm, 0); } // Clear compiled ICs and exception caches diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp index 33d5df425b3..c0fc3aca5a7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp @@ -56,7 +56,7 @@ void HdrSeq::add(double val) { int mag; if (v > 0) { mag = 0; - while (v > 1) { + while (v >= 1) { mag++; v /= 10; } @@ -71,7 +71,7 @@ void HdrSeq::add(double val) { int bucket = -MagMinimum + mag; int sub_bucket = (int) (v * ValBuckets); - // Defensively saturate for product bits: + // Defensively saturate for product bits if (bucket < 0) { assert (false, "bucket index (%d) underflow for value (%8.2f)", bucket, val); bucket = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp index 9f9cb2ecaaf..42f91f6a9b8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp @@ -55,7 +55,7 @@ class HdrSeq: public NumberSeq { // Binary magnitude sequence stores the power-of-two histogram. // It has very low memory requirements, and is thread-safe. When accuracy // is not needed, it is preferred over HdrSeq. -class BinaryMagnitudeSeq { +class BinaryMagnitudeSeq : public CHeapObj { private: size_t _sum; size_t* _mags; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp index b7553b7125c..208656c6015 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahPacer.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "runtime/atomic.hpp" +#include "runtime/javaThread.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/threadSMR.hpp" @@ -241,7 +242,13 @@ void ShenandoahPacer::pace_for_alloc(size_t words) { // Threads that are attaching should not block at all: they are not // fully initialized yet. Blocking them would be awkward. // This is probably the path that allocates the thread oop itself. - if (JavaThread::current()->is_attaching_via_jni()) { + // + // Thread which is not an active Java thread should also not block. + // This can happen during VM init when main thread is still not an + // active Java thread. + JavaThread* current = JavaThread::current(); + if (current->is_attaching_via_jni() || + !current->is_active_Java_thread()) { return; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index b828582336c..1cc5686489f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -90,7 +90,7 @@ static oop reference_referent(oop reference) { } static void reference_clear_referent(oop reference) { - java_lang_ref_Reference::clear_referent(reference); + java_lang_ref_Reference::clear_referent_raw(reference); } template diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp index c40ba38f36f..57c0a421f95 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp @@ -68,10 +68,10 @@ bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { return true; } -int* ZBarrierSetNMethod::disarmed_value_address() const { +int* ZBarrierSetNMethod::disarmed_guard_value_address() const { return (int*)ZAddressBadMaskHighOrderBitsAddr; } -ByteSize ZBarrierSetNMethod::thread_disarmed_offset() const { +ByteSize ZBarrierSetNMethod::thread_disarmed_guard_value_offset() const { return ZThreadLocalData::nmethod_disarmed_offset(); } diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp index 8e349d3984a..ed9f06672e7 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp @@ -34,8 +34,8 @@ class ZBarrierSetNMethod : public BarrierSetNMethod { virtual bool nmethod_entry_barrier(nmethod* nm); public: - virtual ByteSize thread_disarmed_offset() const; - virtual int* disarmed_value_address() const; + virtual ByteSize thread_disarmed_guard_value_offset() const; + virtual int* disarmed_guard_value_address() const; }; #endif // SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 0d333626ea0..5abc6ccf580 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -224,6 +224,10 @@ bool ZCollectedHeap::uses_stack_watermark_barrier() const { return true; } +MemoryUsage ZCollectedHeap::memory_usage() { + return _heap.serviceability_memory_pool()->get_memory_usage(); +} + GrowableArray ZCollectedHeap::memory_managers() { GrowableArray memory_managers(2); memory_managers.append(_heap.serviceability_cycle_memory_manager()); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index d1d14576e0b..37f41282c94 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -31,6 +31,7 @@ #include "gc/z/zInitialize.hpp" #include "gc/z/zRuntimeWorkers.hpp" #include "memory/metaspace.hpp" +#include "services/memoryUsage.hpp" class ZDirector; class ZDriver; @@ -90,6 +91,7 @@ class ZCollectedHeap : public CollectedHeap { virtual bool uses_stack_watermark_barrier() const; + virtual MemoryUsage memory_usage(); virtual GrowableArray memory_managers(); virtual GrowableArray memory_pools(); diff --git a/src/hotspot/share/gc/z/zDriver.cpp b/src/hotspot/share/gc/z/zDriver.cpp index 60daf185956..44c0d944cee 100644 --- a/src/hotspot/share/gc/z/zDriver.cpp +++ b/src/hotspot/share/gc/z/zDriver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -222,7 +222,6 @@ bool ZDriver::is_busy() const { void ZDriver::collect(const ZDriverRequest& request) { switch (request.cause()) { case GCCause::_wb_young_gc: - case GCCause::_wb_conc_mark: case GCCause::_wb_full_gc: case GCCause::_dcmd_gc_run: case GCCause::_java_lang_system_gc: diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index 98073c465f3..db4d3775d23 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -197,11 +197,9 @@ void ZNMethod::disarm(nmethod* nm) { bs->disarm(nm); } -void ZNMethod::arm(nmethod* nm, int arm_value) { +void ZNMethod::set_guard_value(nmethod* nm, int value) { BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod(); - if (bs != NULL) { - bs->arm(nm, arm_value); - } + bs->set_guard_value(nm, value); } void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) { @@ -300,9 +298,9 @@ class ZNMethodUnlinkClosure : public NMethodClosure { ZLocker locker(ZNMethod::lock_for_nmethod(nm)); if (ZNMethod::is_armed(nm)) { - // Heal oops and disarm + // Heal oops and arm phase invariantly ZNMethod::nmethod_oops_barrier(nm); - ZNMethod::arm(nm, 0); + ZNMethod::set_guard_value(nm, 0); } // Clear compiled ICs and exception caches diff --git a/src/hotspot/share/gc/z/zNMethod.hpp b/src/hotspot/share/gc/z/zNMethod.hpp index c577b864d73..543a3a21732 100644 --- a/src/hotspot/share/gc/z/zNMethod.hpp +++ b/src/hotspot/share/gc/z/zNMethod.hpp @@ -46,7 +46,7 @@ class ZNMethod : public AllStatic { static bool is_armed(nmethod* nm); static void disarm(nmethod* nm); - static void arm(nmethod* nm, int arm_value); + static void set_guard_value(nmethod* nm, int value); static void nmethod_oops_do(nmethod* nm, OopClosure* cl); static void nmethod_oops_do_inner(nmethod* nm, OopClosure* cl); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index 0c2df388882..042323c8777 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -72,7 +72,7 @@ static oop reference_referent(oop reference) { } static void reference_clear_referent(oop reference) { - java_lang_ref_Reference::clear_referent(reference); + java_lang_ref_Reference::clear_referent_raw(reference); } static oop* reference_discovered_addr(oop reference) { diff --git a/src/hotspot/share/gc/z/zSafeDelete.hpp b/src/hotspot/share/gc/z/zSafeDelete.hpp index f18d1e4153e..62c3495c57b 100644 --- a/src/hotspot/share/gc/z/zSafeDelete.hpp +++ b/src/hotspot/share/gc/z/zSafeDelete.hpp @@ -26,12 +26,13 @@ #include "gc/z/zArray.hpp" #include "gc/z/zLock.hpp" -#include "metaprogramming/removeExtent.hpp" + +#include template class ZSafeDeleteImpl { private: - typedef typename RemoveExtent::type ItemT; + using ItemT = std::remove_extent_t; ZLock* _lock; uint64_t _enabled; diff --git a/src/hotspot/share/gc/z/zSafeDelete.inline.hpp b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp index 9db212bd4c2..460193827e0 100644 --- a/src/hotspot/share/gc/z/zSafeDelete.inline.hpp +++ b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp @@ -27,9 +27,10 @@ #include "gc/z/zSafeDelete.hpp" #include "gc/z/zArray.inline.hpp" -#include "metaprogramming/isArray.hpp" #include "utilities/debug.hpp" +#include + template ZSafeDeleteImpl::ZSafeDeleteImpl(ZLock* lock) : _lock(lock), @@ -49,7 +50,7 @@ bool ZSafeDeleteImpl::deferred_delete(ItemT* item) { template void ZSafeDeleteImpl::immediate_delete(ItemT* item) { - if (IsArray::value) { + if (std::is_array::value) { delete [] item; } else { delete item; diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 07dd0513b96..98e0233887c 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -310,10 +310,13 @@ JNIEXPORT jobjectArray JNICALL JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads); JNIEXPORT jobject JNICALL -JVM_ExtentLocalCache(JNIEnv *env, jclass threadClass); +JVM_ScopedValueCache(JNIEnv *env, jclass threadClass); JNIEXPORT void JNICALL -JVM_SetExtentLocalCache(JNIEnv *env, jclass threadClass, jobject theCache); +JVM_SetScopedValueCache(JNIEnv *env, jclass threadClass, jobject theCache); + +JNIEXPORT jobject JNICALL +JVM_FindScopedValueBindings(JNIEnv *env, jclass threadClass); JNIEXPORT jlong JNICALL JVM_GetNextThreadIdOffset(JNIEnv *env, jclass threadClass); @@ -742,6 +745,8 @@ JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls); #define JVM_EnsureMaterializedForStackWalk(env, value) \ do {} while(0) // Nothing to do. The fact that the value escaped // through a native method is enough. +JNIEXPORT void JNICALL +JVM_EnsureMaterializedForStackWalk_func(JNIEnv* env, jobject vthread, jobject value); JNIEXPORT jobject JNICALL JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls); diff --git a/src/hotspot/share/interpreter/bootstrapInfo.cpp b/src/hotspot/share/interpreter/bootstrapInfo.cpp index 24e9afff78b..e37363aeb44 100644 --- a/src/hotspot/share/interpreter/bootstrapInfo.cpp +++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp @@ -230,9 +230,9 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { st = st ? st : tty; if (_indy_index != -1) - sprintf(what, "indy#%d", decode_indy_index()); + os::snprintf_checked(what, sizeof(what), "indy#%d", decode_indy_index()); else - sprintf(what, "condy"); + os::snprintf_checked(what, sizeof(what), "condy"); bool have_msg = (msg != NULL && strlen(msg) > 0); st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s", (have_msg ? msg : ""), (have_msg ? " " : ""), @@ -251,11 +251,11 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { for (int i = 0; i < _argc; i++) { int pos = (int) strlen(argbuf); if (pos + 20 > (int)sizeof(argbuf)) { - sprintf(argbuf + pos, "..."); + os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "..."); break; } if (i > 0) argbuf[pos++] = ','; - sprintf(argbuf+pos, "%d", arg_index(i)); + os::snprintf_checked(argbuf+pos, sizeof(argbuf) - pos, "%d", arg_index(i)); } st->print_cr(" argument indexes: {%s}", argbuf); } diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 6c169ea4317..9d6640f4d46 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -194,7 +194,7 @@ JRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* current, Bytecodes:: if (rindex < 0) rindex = m->constants()->cp_to_object_index(ldc2.pool_index()); if (rindex >= 0) { - oop coop = m->constants()->resolved_references()->obj_at(rindex); + oop coop = m->constants()->resolved_reference_at(rindex); oop roop = (result == NULL ? Universe::the_null_sentinel() : result); assert(roop == coop, "expected result for assembly code"); } @@ -372,6 +372,9 @@ JRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* current CHECK); // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); + // Remove the ScopedValue bindings in case we got a StackOverflowError + // while we were trying to manipulate ScopedValue bindings. + current->clear_scopedValueBindings(); THROW_HANDLE(exception); JRT_END @@ -383,6 +386,9 @@ JRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* Universe::delayed_stack_overflow_error_message()); // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); + // Remove the ScopedValue bindings in case we got a StackOverflowError + // while we were trying to manipulate ScopedValue bindings. + current->clear_scopedValueBindings(); THROW_HANDLE(exception); JRT_END diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index db1ed705d13..38194575f12 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -814,7 +814,7 @@ static void trace_method_resolution(const char* prefix, st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", prefix, (klass == NULL ? "" : klass->internal_name()), - (resolved_klass == NULL ? "" : resolved_klass->internal_name()), + resolved_klass->internal_name(), Method::name_and_sig_as_C_string(resolved_klass, method->name(), method->signature()), @@ -970,17 +970,16 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, Symbol* field = link_info.name(); Symbol* sig = link_info.signature(); - if (resolved_klass == NULL) { - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); - } - // Resolve instance field Klass* sel_klass = resolved_klass->find_field(field, sig, &fd); // check if field exists; i.e., if a klass containing the field def has been selected if (sel_klass == NULL) { ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); + stringStream ss; + ss.print("Class %s does not have member field '", resolved_klass->external_name()); + sig->print_as_field_external_type(&ss); + ss.print(" %s'", field->as_C_string()); + THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), ss.as_string()); } // Access checking may be turned off when calling from within the VM. diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index b1a7274c6bc..9686495c0af 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -154,26 +154,29 @@ class LinkInfo : public StackObj { AccessCheck check_access = AccessCheck::required, LoaderConstraintCheck check_loader_constraints = LoaderConstraintCheck::required, constantTag tag = JVM_CONSTANT_Invalid) : - _name(name), - _signature(signature), _resolved_klass(resolved_klass), _current_klass(current_klass), _current_method(methodHandle()), - _check_access(check_access == AccessCheck::required), - _check_loader_constraints(check_loader_constraints == LoaderConstraintCheck::required), _tag(tag) {} + _name(name), + _signature(signature), + _resolved_klass(resolved_klass), + _current_klass(current_klass), + _current_method(methodHandle()), + _check_access(check_access == AccessCheck::required), + _check_loader_constraints(check_loader_constraints == LoaderConstraintCheck::required), + _tag(tag) { + assert(_resolved_klass != nullptr, "must always have a resolved_klass"); + } LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, const methodHandle& current_method, AccessCheck check_access = AccessCheck::required, LoaderConstraintCheck check_loader_constraints = LoaderConstraintCheck::required, constantTag tag = JVM_CONSTANT_Invalid) : - _name(name), - _signature(signature), _resolved_klass(resolved_klass), _current_klass(current_method->method_holder()), _current_method(current_method), - _check_access(check_access == AccessCheck::required), - _check_loader_constraints(check_loader_constraints == LoaderConstraintCheck::required), _tag(tag) {} - + LinkInfo(resolved_klass, name, signature, current_method->method_holder(), check_access, check_loader_constraints, tag) { + _current_method = current_method; + } - // Case where we just find the method and don't check access against the current class + // Case where we just find the method and don't check access against the current class, used by JavaCalls LinkInfo(Klass* resolved_klass, Symbol*name, Symbol* signature) : - _name(name), - _signature(signature), _resolved_klass(resolved_klass), _current_klass(NULL), _current_method(methodHandle()), - _check_access(false), _check_loader_constraints(false), _tag(JVM_CONSTANT_Invalid) {} + LinkInfo(resolved_klass, name, signature, nullptr, AccessCheck::skip, LoaderConstraintCheck::skip, + JVM_CONSTANT_Invalid) {} // accessors Symbol* name() const { return _name; } diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index d82feb79915..7d8ab5110cf 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -2127,7 +2127,7 @@ void BytecodeInterpreter::run(interpreterState istate) { case JVM_CONSTANT_String: { - oop result = constants->resolved_references()->obj_at(index); + oop result = constants->resolved_reference_at(index); if (result == NULL) { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); SET_STACK_OBJECT(THREAD->vm_result(), 0); @@ -2232,7 +2232,7 @@ void BytecodeInterpreter::run(interpreterState istate) { // This kind of CP cache entry does not need to match the flags byte, because // there is a 1-1 relation between bytecode type and CP entry type. ConstantPool* constants = METHOD->constants(); - oop result = constants->resolved_references()->obj_at(index); + oop result = constants->resolved_reference_at(index); if (result == NULL) { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp index 54f056dc432..4e4856b84d5 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp @@ -1524,22 +1524,19 @@ static ClassFileStream* retransform_bytes(const Klass* existing_klass, const Cla DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); jint size_of_new_bytes = 0; unsigned char* new_bytes = NULL; - { - ResourceMark rm(THREAD); - const ClassFileStream* const stream = parser.clone_stream(); - assert(stream != NULL, "invariant"); - const jclass clazz = static_cast(JfrJavaSupport::local_jni_handle(existing_klass->java_mirror(), THREAD)); - JfrUpcalls::on_retransform(JfrTraceId::load_raw(existing_klass), - clazz, - stream->length(), - stream->buffer(), - &size_of_new_bytes, - &new_bytes, - THREAD); - JfrJavaSupport::destroy_local_jni_handle(clazz); - if (has_pending_exception(THREAD)) { - return NULL; - } + const ClassFileStream* const stream = parser.clone_stream(); + assert(stream != NULL, "invariant"); + const jclass clazz = static_cast(JfrJavaSupport::local_jni_handle(existing_klass->java_mirror(), THREAD)); + JfrUpcalls::on_retransform(JfrTraceId::load_raw(existing_klass), + clazz, + stream->length(), + stream->buffer(), + &size_of_new_bytes, + &new_bytes, + THREAD); + JfrJavaSupport::destroy_local_jni_handle(clazz); + if (has_pending_exception(THREAD)) { + return NULL; } assert(new_bytes != NULL, "invariant"); assert(size_of_new_bytes > 0, "invariant"); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 8ae2eb0c276..cf4aae2add5 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -238,8 +238,8 @@ JVM_ENTRY_NO_ENV(void, jfr_mark_chunk_final(JNIEnv * env, jobject jvm)) JfrRepository::mark_chunk_final(); JVM_END -JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when)) - JfrPeriodicEventSet::requestEvent((JfrEventId)eventTypeId); +JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong event_type_id, jlong timestamp, jlong periodic_type)) + JfrPeriodicEventSet::requestEvent((JfrEventId)event_type_id, timestamp, static_cast(periodic_type)); return thread->has_pending_exception() ? JNI_FALSE : JNI_TRUE; JVM_END diff --git a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp index 673b647e309..480c01ed2fe 100644 --- a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp +++ b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp @@ -141,9 +141,7 @@ void JfrUpcalls::on_retransform(jlong trace_id, CHECK); assert(new_byte_array != NULL, "invariant"); assert(new_bytes_length > 0, "invariant"); - // memory space must be malloced as mtInternal - // as it will be deallocated by JVMTI routines - unsigned char* const new_bytes = (unsigned char* const)os::malloc(new_bytes_length, mtInternal); + unsigned char* const new_bytes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, unsigned char, new_bytes_length); if (new_bytes == NULL) { log_error_and_throw_oom(new_bytes_length, THREAD); // unwinds } diff --git a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp index 037d320c7a1..4644fa49f66 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp @@ -48,7 +48,7 @@ template void RootSetClosure::do_oop(oop* ref) { assert(ref != NULL, "invariant"); assert(is_aligned(ref, HeapWordSize), "invariant"); - if (*ref != NULL) { + if (NativeAccess<>::oop_load(ref) != nullptr) { _delegate->do_root(UnifiedOopRef::encode_in_native(ref)); } } @@ -64,14 +64,42 @@ void RootSetClosure::do_oop(narrowOop* ref) { class RootSetClosureMarkScope : public MarkScope {}; +template +class RawRootClosure : public OopClosure { + Delegate* _delegate; + +public: + RawRootClosure(Delegate* delegate) : _delegate(delegate) {} + + void do_oop(oop* ref) { + assert(ref != NULL, "invariant"); + assert(is_aligned(ref, HeapWordSize), "invariant"); + if (*ref != nullptr) { + _delegate->do_root(UnifiedOopRef::encode_as_raw(ref)); + } + } + + void do_oop(narrowOop* ref) { + assert(ref != NULL, "invariant"); + assert(is_aligned(ref, HeapWordSize), "invariant"); + if (!CompressedOops::is_null(*ref)) { + _delegate->do_root(UnifiedOopRef::encode_as_raw(ref)); + } + } +}; + template void RootSetClosure::process() { RootSetClosureMarkScope mark_scope; + CLDToOopClosure cldt_closure(this, ClassLoaderData::_claim_none); ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); - // We don't follow code blob oops, because they have misaligned oops. - Threads::oops_do(this, NULL); + OopStorageSet::strong_oops_do(this); + + // We don't follow code blob oops, because they have misaligned oops. + RawRootClosure rrc(_delegate); + Threads::oops_do(&rrc, NULL); } template class RootSetClosure; diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.hpp index c697181fd27..dad0a7cd08f 100644 --- a/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.hpp +++ b/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.hpp @@ -29,6 +29,15 @@ #include "utilities/globalDefinitions.hpp" struct UnifiedOopRef { + static const uintptr_t tag_mask = LP64_ONLY(0b111) NOT_LP64(0b011); + static const uintptr_t native_tag = 0b001; + static const uintptr_t raw_tag = 0b010; + static const uintptr_t narrow_tag = LP64_ONLY(0b100) NOT_LP64(0); + STATIC_ASSERT((native_tag & raw_tag) == 0); + STATIC_ASSERT((native_tag & narrow_tag) == 0); + STATIC_ASSERT((raw_tag & narrow_tag) == 0); + STATIC_ASSERT((native_tag | raw_tag | narrow_tag) == tag_mask); + uintptr_t _value; template @@ -36,14 +45,17 @@ struct UnifiedOopRef { bool is_narrow() const; bool is_native() const; + bool is_raw() const; bool is_null() const; oop dereference() const; static UnifiedOopRef encode_in_native(const narrowOop* ref); static UnifiedOopRef encode_in_native(const oop* ref); - static UnifiedOopRef encode_in_heap(const oop* ref); + static UnifiedOopRef encode_as_raw(const narrowOop* ref); + static UnifiedOopRef encode_as_raw(const oop* ref); static UnifiedOopRef encode_in_heap(const narrowOop* ref); + static UnifiedOopRef encode_in_heap(const oop* ref); static UnifiedOopRef encode_null(); }; diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp index cfa11c2ff77..d5bac9f5b13 100644 --- a/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp +++ b/src/hotspot/share/jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp @@ -32,7 +32,7 @@ template inline T UnifiedOopRef::addr() const { - return reinterpret_cast(_value & ~uintptr_t(3)); + return reinterpret_cast(UnifiedOopRef::addr()); } // Visual Studio 2019 and earlier have a problem with reinterpret_cast @@ -42,47 +42,70 @@ inline T UnifiedOopRef::addr() const { // this specialization provides a workaround. template<> inline uintptr_t UnifiedOopRef::addr() const { - return _value & ~uintptr_t(3); + return (_value & ~tag_mask) LP64_ONLY(>> 1); } inline bool UnifiedOopRef::is_narrow() const { - return _value & 1; + return (_value & narrow_tag) != 0; } inline bool UnifiedOopRef::is_native() const { - return _value & 2; + return (_value & native_tag) != 0; +} + +inline bool UnifiedOopRef::is_raw() const { + return (_value & raw_tag) != 0; } inline bool UnifiedOopRef::is_null() const { return _value == 0; } -inline UnifiedOopRef UnifiedOopRef::encode_in_native(const narrowOop* ref) { +template +inline UnifiedOopRef create_with_tag(T ref, uintptr_t tag) { assert(ref != NULL, "invariant"); - UnifiedOopRef result = { reinterpret_cast(ref) | 3 }; - assert(result.addr() == ref, "sanity"); + + uintptr_t value = reinterpret_cast(ref); + +#ifdef _LP64 + // tag_mask is 3 bits. When ref is a narrowOop* we only have 2 alignment + // bits, because of the 4 byte alignment of compressed oops addresses. + // Shift up to make way for one more bit. + assert((value & (1ull << 63)) == 0, "Unexpected high-order bit"); + value <<= 1; +#endif + assert((value & UnifiedOopRef::tag_mask) == 0, "Unexpected low-order bits"); + + UnifiedOopRef result = { value | tag }; + assert(result.addr() == ref, "sanity"); return result; } +inline UnifiedOopRef UnifiedOopRef::encode_in_native(const narrowOop* ref) { + NOT_LP64(ShouldNotReachHere()); + return create_with_tag(ref, native_tag | narrow_tag); +} + inline UnifiedOopRef UnifiedOopRef::encode_in_native(const oop* ref) { - assert(ref != NULL, "invariant"); - UnifiedOopRef result = { reinterpret_cast(ref) | 2 }; - assert(result.addr() == ref, "sanity"); - return result; + return create_with_tag(ref, native_tag); +} + +inline UnifiedOopRef UnifiedOopRef::encode_as_raw(const narrowOop* ref) { + NOT_LP64(ShouldNotReachHere()); + return create_with_tag(ref, raw_tag | narrow_tag); +} + +inline UnifiedOopRef UnifiedOopRef::encode_as_raw(const oop* ref) { + return create_with_tag(ref, raw_tag); } inline UnifiedOopRef UnifiedOopRef::encode_in_heap(const narrowOop* ref) { - assert(ref != NULL, "invariant"); - UnifiedOopRef result = { reinterpret_cast(ref) | 1 }; - assert(result.addr() == ref, "sanity"); - return result; + NOT_LP64(ShouldNotReachHere()); + return create_with_tag(ref, narrow_tag); } inline UnifiedOopRef UnifiedOopRef::encode_in_heap(const oop* ref) { - assert(ref != NULL, "invariant"); - UnifiedOopRef result = { reinterpret_cast(ref) | 0 }; - assert(result.addr() == ref, "sanity"); - return result; + return create_with_tag(ref, 0); } inline UnifiedOopRef UnifiedOopRef::encode_null() { @@ -91,14 +114,23 @@ inline UnifiedOopRef UnifiedOopRef::encode_null() { } inline oop UnifiedOopRef::dereference() const { - if (is_native()) { + if (is_raw()) { + if (is_narrow()) { + NOT_LP64(ShouldNotReachHere()); + return RawAccess<>::oop_load(addr()); + } else { + return *addr(); + } + } else if (is_native()) { if (is_narrow()) { + NOT_LP64(ShouldNotReachHere()); return NativeAccess::oop_load(addr()); } else { return NativeAccess::oop_load(addr()); } } else { if (is_narrow()) { + NOT_LP64(ShouldNotReachHere()); return HeapAccess::oop_load(addr()); } else { return HeapAccess::oop_load(addr()); diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index b145d3d080c..05b5da0adf2 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -1,7 +1,7 @@ Phi + x = (x - 1) ^ 1; + // Problem: this looks like a loop, but we have no LoopNode + // We have no LoopNode, because this is all in an infinite + // loop, and during PhaseIdealLoop::build_loop_tree we do not + // attach the loops of an infinite loop to the loop tree, + // and hence we do not get to call beautify_loop on these loops + // which would have turned the Region into a LoopNode. + } while (x < 0); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java b/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java new file mode 100644 index 00000000000..51c6b016f34 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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 + * @key stress randomness + * @bug 8298520 + * @requires vm.compiler2.enabled + * @summary Dying subgraph confuses logic that tries to find the OpaqueZeroTripGuard. + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestUnexpectedOpaque1::* -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:StressSeed=1642564308 compiler.loopopts.TestUnexpectedOpaque1 + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestUnexpectedOpaque1::* -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN compiler.loopopts.TestUnexpectedOpaque1 + */ + +package compiler.loopopts; + +public class TestUnexpectedOpaque1 { + + static int cnt = 0; + + static int test() { + int res = 42; + for (int i = 500; i > 0; --i) { + res |= 1; + if (res != 0) { + return 43; + } + cnt++; + } + return Float.floatToIntBits(44F); + } + + public static void main(String[] args) { + test(); + } +} diff --git a/test/hotspot/jtreg/compiler/profiling/TestTypeProfileArgsLimit.java b/test/hotspot/jtreg/compiler/profiling/TestTypeProfileArgsLimit.java new file mode 100644 index 00000000000..a6d5da5a409 --- /dev/null +++ b/test/hotspot/jtreg/compiler/profiling/TestTypeProfileArgsLimit.java @@ -0,0 +1,44 @@ +/* + * 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 TestTypeProfileArgsLimit + * @bug 8295406 + * @summary Tests execution with TypeProfileArgsLimit=0 TypeProfileLevel=222. + * + * @run main/othervm -XX:TypeProfileArgsLimit=0 -XX:TypeProfileLevel=222 compiler.profiling.TestTypeProfileArgsLimit + * @run main/othervm -XX:TypeProfileArgsLimit=0 -XX:TypeProfileLevel=212 compiler.profiling.TestTypeProfileArgsLimit + * @run main/othervm -XX:TypeProfileArgsLimit=0 -XX:TypeProfileLevel=202 compiler.profiling.TestTypeProfileArgsLimit + * @run main/othervm -XX:TypeProfileParmsLimit=0 -XX:TypeProfileLevel=222 compiler.profiling.TestTypeProfileArgsLimit + * @run main/othervm -XX:TypeProfileParmsLimit=0 -XX:TypeProfileArgsLimit=0 -XX:TypeProfileLevel=222 compiler.profiling.TestTypeProfileArgsLimit + * @run main/othervm -XX:TypeProfileParmsLimit=-1 -XX:TypeProfileArgsLimit=0 -XX:TypeProfileLevel=222 compiler.profiling.TestTypeProfileArgsLimit + */ + +package compiler.profiling; + +public class TestTypeProfileArgsLimit { + public static void main(String args[]) { + System.out.println("Passed"); + } +} + diff --git a/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java b/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java new file mode 100644 index 00000000000..f9dd8b2dcb6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java @@ -0,0 +1,160 @@ +/* + * 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 +* @key stress randomness +* @bug 8299259 +* @requires vm.compiler2.enabled +* @summary Test various cases of divisions/modulo which should not be split through iv phis. +* @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:LoopUnrollLimit=0 -XX:+StressGCM -XX:StressSeed=884154126 +* -XX:CompileCommand=compileonly,compiler.splitif.TestSplitDivisionThroughPhi::* +* compiler.splitif.TestSplitDivisionThroughPhi +*/ + +/** +* @test +* @key stress randomness +* @bug 8299259 +* @requires vm.compiler2.enabled +* @summary Test various cases of divisions/modulo which should not be split through iv phis. +* @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:LoopUnrollLimit=0 -XX:+StressGCM +* -XX:CompileCommand=compileonly,compiler.splitif.TestSplitDivisionThroughPhi::* +* compiler.splitif.TestSplitDivisionThroughPhi +*/ + +package compiler.splitif; + +public class TestSplitDivisionThroughPhi { + static int iFld; + static long lFld; + static boolean flag; + + + public static void main(String[] strArr) { + for (int i = 0; i < 5000; i++) { + testPushDivIThruPhi(); + testPushDivIThruPhiInChain(); + testPushModIThruPhi(); + testPushModIThruPhiInChain(); + testPushDivLThruPhi(); + testPushDivLThruPhiInChain(); + testPushModLThruPhi(); + testPushModLThruPhiInChain(); + } + } + + // Already fixed by JDK-8248552. + static void testPushDivIThruPhi() { + for (int i = 10; i > 1; i -= 2) { + // The Div node is only split in later loop opts phase because the zero divisor check is only removed + // in IGVN after the first loop opts phase. + // + // iv phi i type: [2..10] + // When splitting the DivI through the iv phi, it ends up on the back edge with the trip count decrement + // as input which has type [0..8]. We end up executing a division by zero on the last iteration because + // the DivI it is not pinned to the loop exit test and can freely float above the loop exit check. + iFld = 10 / i; + } + } + + // Same as above but with an additional Mul node between the iv phi and the Div node. Both nodes are split through + // the iv phi in one pass of Split If. + static void testPushDivIThruPhiInChain() { + for (int i = 10; i > 1; i -= 2) { + // Empty one iteration loop which is only removed after split if in first loop opts phase. This prevents + // that the Mul node is already split through the iv phi while the Div node cannot be split yet due to + // the zero divisor check which can only be removed in the IGVN after the first loop opts pass. + for (int j = 0; j < 1; j++) { + } + iFld = 10 / (i * 100); + } + } + + // Already fixed by JDK-8248552. + static void testPushModIThruPhi() { + for (int i = 10; i > 1; i -= 2) { + iFld = 10 / i; + } + } + + // Same as above but with ModI. + static void testPushModIThruPhiInChain() { + for (int i = 10; i > 1; i -= 2) { + for (int j = 0; j < 1; j++) { + } + iFld = 10 / (i * 100); + } + } + + // Long cases only trigger since JDK-8256655. + + // Same as above but with DivL. + static void testPushDivLThruPhi() { + for (long i = 10; i > 1; i -= 2) { + lFld = 10L / i; + + // Loop that is not removed such that we do not transform the outer LongCountedLoop (only done if innermost) + for (int j = 0; j < 10; j++) { + flag = !flag; + } + } + } + + // Same as above but with DivL. + static void testPushDivLThruPhiInChain() { + for (long i = 10; i > 1; i -= 2) { + for (int j = 0; j < 1; j++) { + } + lFld = 10L / (i * 100L); + + for (int j = 0; j < 10; j++) { + flag = !flag; + } + } + } + + // Same as above but with ModL + static void testPushModLThruPhi() { + for (long i = 10; i > 1; i -= 2) { + lFld = 10L % i; + + for (int j = 0; j < 10; j++) { + flag = !flag; + } + } + } + + // Same as above but with ModL + static void testPushModLThruPhiInChain() { + for (long i = 10; i > 1; i -= 2) { + for (int j = 0; j < 1; j++) { + } + lFld = 10L % (i * 100L); + + for (int j = 0; j < 10; j++) { + flag = !flag; + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java b/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java new file mode 100644 index 00000000000..5c57e479307 --- /dev/null +++ b/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8297345 + * @summary C2: SIGSEGV in PhaseIdealLoop::push_pinned_nodes_thru_region + * @requires vm.gc.Parallel + * + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation + * -XX:CompileOnly=TestCheckCastPPBecomesTOP::test1 -XX:LoopMaxUnroll=0 + * -XX:CompileCommand=dontinline,TestCheckCastPPBecomesTOP::notInlined -XX:+UseParallelGC TestCheckCastPPBecomesTOP + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation + * -XX:CompileOnly=TestCheckCastPPBecomesTOP::test1 -XX:LoopMaxUnroll=0 + * -XX:CompileCommand=dontinline,TestCheckCastPPBecomesTOP::notInlined -XX:+UseParallelGC -XX:-UseCompressedClassPointers TestCheckCastPPBecomesTOP + * + */ + +public class TestCheckCastPPBecomesTOP { + private static I field; + private static I field2; + private static I field3; + private static volatile int barrier; + + public static void main(String[] args) { + A a = new A(); + B b = new B(); + for (int i = 0; i < 100_000; i++) { + test1Helper3(5); + field2 = field = a; + test1Helper1(b, 100, 100); + test1Helper1(b, 100, 100); + test1Helper1(b, 100, 100); + field2 = field = b; + test1Helper1(b, 100, 100); + test1Helper1(b, 100, 100); + + field2 = field = a; + test1Helper1(b, 10, 100); + test1Helper1(b, 10, 100); + test1Helper1(b, 10, 100); + field2 = field = b; + test1Helper1(b, 10, 100); + test1Helper1(b, 10, 100); + + field2 = field = a; + test1Helper1(b, 10, 10); + test1Helper1(b, 10, 10); + test1Helper1(b, 10, 10); + field2 = field = b; + test1Helper1(b, 10, 10); + test1Helper1(b, 10, 10); + + field2 = field = a; + test1Helper2(b, true); + field2 = field = b; + test1Helper2(b, true); + + test1(false); + } + } + + + private static void test1(boolean flag1) { + I f = field; + if (f == null) { + } + test1Helper3(10); + test1Helper2(f, flag1); + + for (int j = 0; j < 10; j++) { + for (int k = 0; k < 10; k++) { + for (int l = 0; l < 10; l++) { + + } + } + } + } + + private static void test1Helper3(int stop) { + int i; + for (i = 0; i < stop; i++) { + + } + if (i != 10) { + barrier = 0x42; + } + } + + + private static void test1Helper2(I f2, boolean flag1) { + if (flag1) { + if (f2 == null) { + + } + int i; + for (i = 0; i < 10; i++) { + } + int j; + for (j = 0; j < 10; j++) { + for (int k = 0; k < 10; k++) { + + } + } + test1Helper1(f2, i, j); + } + } + + private static void test1Helper1(I f2, int i, int j) { + I f1 = field; + if (f1 == null) { + + } + I f3 = field2; + if (f3 == null) { + } + field2 = f3; + field = f1; + if (i == 10) { + if (j == 10) { + f1.m1(); + } else { + f1 = f3; + } + f3.m2(f1); + } else { + f1 = f3; + } + I f4 = field2; + field = f1; + f4.m3(f1, f2); + I f5 = field; + barrier = 0x42; + f5.m4(f2); + } + + private static void notInlined(Object o1, Object o2) { + + } + + interface I { + void m1(); + void m2(I f); + void m3(I f1, I f2); + + void m4(I f2); + } + + static class A implements I { + public void m1() { + + } + + public void m2(I f) { + f.m1(); + } + + public void m3(I f1, I f2) { + f1.m1(); + f2.m1(); + } + + public void m4(I f2) { + notInlined(this, f2); + field3 = this; + } + } + + static class B implements I { + public void m1() { + + } + + public void m2(I f) { + f.m1(); + } + + public void m3(I f1, I f2) { + f1.m1(); + f2.m1(); + } + + public void m4(I f2) { + notInlined(this, f2); + field3 = this; + } + + } +} diff --git a/test/hotspot/jtreg/gtest/ArenaGtests.java b/test/hotspot/jtreg/compiler/types/TestExactArrayOfBasicType.java similarity index 62% rename from test/hotspot/jtreg/gtest/ArenaGtests.java rename to test/hotspot/jtreg/compiler/types/TestExactArrayOfBasicType.java index ee8ec94e456..4ff660cfcec 100644 --- a/test/hotspot/jtreg/gtest/ArenaGtests.java +++ b/test/hotspot/jtreg/compiler/types/TestExactArrayOfBasicType.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2022, 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 @@ -20,21 +19,28 @@ * 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. - * */ /* - * Note: This runs the Arena portion of the gtests with UseMallocOnly - * (restricted to debug since UseMallocOnly is debug-only) + * @test + * @bug 8297556 + * @summary Parse::check_interpreter_type fails with assert "must constrain OSR typestate" + * + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileOnly=TestExactArrayOfBasicType::test TestExactArrayOfBasicType + * */ -/* @test - * @bug 8271242 - * @summary Run arena tests with UseMallocOnly - * @requires vm.debug - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=Arena* -XX:+UseMallocOnly - */ + +public class TestExactArrayOfBasicType { + public static void test() { + int[][][][][] array = new int[1][2][3][4][5]; + + for (int i = 0; i < 50_000; ++i) { + array[0] = new int[0][1][2][3]; + } + } + + public static void main(String args[]) { + test(); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java new file mode 100644 index 00000000000..35f357c22f2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 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 compiler.vectorapi; + +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.VectorMask; + +/* + * @test + * @bug 8292289 + * @summary Test idealization of VectorTest intrinsics to eliminate + * the materialization of the result as an int + * @modules jdk.incubator.vector + * @library /test/lib / + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*sse4.*" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) + * | os.arch == "aarch64" + * @run driver compiler.vectorapi.TestVectorTest + */ +public class TestVectorTest { + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } + + @DontInline + public int call() { return 1; } + + @Test + @IR(failOn = {IRNode.CMP_I, IRNode.CMOVE_I}) + @IR(counts = {IRNode.VECTOR_TEST, "1"}) + public int branch(long maskLong) { + var mask = VectorMask.fromLong(ByteVector.SPECIES_PREFERRED, maskLong); + return mask.allTrue() ? call() : 0; + } + + @Test + @IR(failOn = {IRNode.CMP_I}) + @IR(counts = {IRNode.VECTOR_TEST, "1", IRNode.CMOVE_I, "1"}) + public int cmove(long maskLong) { + var mask = VectorMask.fromLong(ByteVector.SPECIES_PREFERRED, maskLong); + return mask.allTrue() ? 1 : 0; + } + + @Run(test = {"branch", "cmove"}) + public void run() { + branch(-1); + branch(100); + cmove(-1); + cmove(100); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorGatherScatterTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorGatherScatterTest.java index fe626e5246d..4298f1d7000 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorGatherScatterTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorGatherScatterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ public class VectorGatherScatterTest { ia[i] = i; la[i] = RD.nextLong(25); da[i] = RD.nextDouble(25.0); - m[i] = RD.nextBoolean(); + m[i] = i % 2 == 0; } } @@ -102,6 +102,8 @@ public static void testLoadGather() { @IR(counts = { IRNode.LOAD_VECTOR_GATHER_MASKED, ">= 1" }) public static void testLoadGatherMasked() { VectorMask mask = VectorMask.fromArray(L_SPECIES, m, 0); + // "mask" is guaranteed to be not alltrue, in case the masked + // gather load is optimized to the non-masked version. LongVector av = LongVector.fromArray(L_SPECIES, la, 0, ia, 0, mask); av.intoArray(lr, 0); IntVector bv = IntVector.fromArray(I_SPECIES, ia, 0); @@ -132,6 +134,8 @@ public static void testStoreScatter() { public static void testStoreScatterMasked() { VectorMask mask = VectorMask.fromArray(D_SPECIES, m, 0); DoubleVector av = DoubleVector.fromArray(D_SPECIES, da, 0); + // "mask" is guaranteed to be not alltrue, in case the masked + // scatter store is optimized to the non-masked version. av.intoArray(dr, 0, ia, 0, mask); IntVector bv = IntVector.fromArray(I_SPECIES, ia, 0); bv.add(0).intoArray(ir, 0); diff --git a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java index 7a71a00e6e9..e15a4c834cd 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java @@ -34,7 +34,7 @@ * @library /test/lib / * @requires vm.compiler2.enabled * @requires (os.simpleArch == "x64" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) - * | os.arch == "aarch64" | os.arch == "riscv64" + * | os.arch == "aarch64" | (os.arch == "riscv64" & vm.opt.UseRVV == true) * @run driver compiler.c2.irTests.TestAutoVecIntMinMax */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java b/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java index ae7cb037739..d5a3de09123 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,8 +78,8 @@ public class TestEor3AArch64 { // Test for eor3 Neon and SVE2 instruction for integers @Test - @IR(counts = {"veor3_neon", "> 0"}, applyIf = {"MaxVectorSize", "16"}, applyIfCPUFeature = {"sha3", "true"}) - @IR(counts = {"veor3_sve", "> 0"}, applyIfAnd = {"UseSVE", "2", "MaxVectorSize", "> 16"}) + @IR(counts = {IRNode.XOR3_NEON, "> 0"}, applyIf = {"MaxVectorSize", "16"}, applyIfCPUFeature = {"sha3", "true"}) + @IR(counts = {IRNode.XOR3_SVE, "> 0"}, applyIfAnd = {"UseSVE", "2", "MaxVectorSize", "> 16"}) public static void testIntEor3() { for (int i = 0; i < LENGTH; i++) { ir[i] = ia[i] ^ ib[i] ^ ic[i]; @@ -96,8 +96,8 @@ public static void testIntEor3_runner() { // Test for eor3 Neon and SVE2 instruction for longs @Test - @IR(counts = {"veor3_neon", "> 0"}, applyIf = {"MaxVectorSize", "16"}, applyIfCPUFeature = {"sha3", "true"}) - @IR(counts = {"veor3_sve", "> 0"}, applyIfAnd = {"UseSVE", "2", "MaxVectorSize", "> 16"}) + @IR(counts = {IRNode.XOR3_NEON, "> 0"}, applyIf = {"MaxVectorSize", "16"}, applyIfCPUFeature = {"sha3", "true"}) + @IR(counts = {IRNode.XOR3_SVE, "> 0"}, applyIfAnd = {"UseSVE", "2", "MaxVectorSize", "> 16"}) public static void testLongEor3() { for (int i = 0; i < LENGTH; i++) { lr[i] = la[i] ^ lb[i] ^ lc[i]; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java new file mode 100644 index 00000000000..e84b734144e --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 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 8294588 + * @summary Auto-vectorize Float.floatToFloat16, Float.float16ToFloat APIs + * @requires vm.compiler2.enabled + * @requires os.simpleArch == "x64" + * @library /test/lib / + * @run driver compiler.vectorization.TestFloatConversionsVector + */ + +package compiler.vectorization; + +import compiler.lib.ir_framework.*; + +public class TestFloatConversionsVector { + private static final int ARRLEN = 1024; + private static final int ITERS = 11000; + private static float [] finp; + private static short [] sout; + private static short [] sinp; + private static float [] fout; + + public static void main(String args[]) { + TestFramework.runWithFlags("-XX:-TieredCompilation", + "-XX:CompileThresholdScaling=0.3"); + System.out.println("PASSED"); + } + + @Test + @IR(counts = {IRNode.VECTOR_CAST_F2HF, "> 0"}, applyIfCPUFeatureOr = {"avx512f", "true", "f16c", "true"}) + public void test_float_float16(short[] sout, float[] finp) { + for (int i = 0; i < finp.length; i++) { + sout[i] = Float.floatToFloat16(finp[i]); + } + } + + @Run(test = {"test_float_float16"}, mode = RunMode.STANDALONE) + public void kernel_test_float_float16() { + finp = new float[ARRLEN]; + sout = new short[ARRLEN]; + + for (int i = 0; i < ARRLEN; i++) { + finp[i] = (float) i * 1.4f; + } + + for (int i = 0; i < ITERS; i++) { + test_float_float16(sout, finp); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_CAST_HF2F, "> 0"}, applyIfCPUFeatureOr = {"avx512f", "true", "f16c", "true"}) + public void test_float16_float(float[] fout, short[] sinp) { + for (int i = 0; i < sinp.length; i++) { + fout[i] = Float.float16ToFloat(sinp[i]); + } + } + + @Run(test = {"test_float16_float"}, mode = RunMode.STANDALONE) + public void kernel_test_float16_float() { + sinp = new short[ARRLEN]; + fout = new float[ARRLEN]; + + for (int i = 0; i < ARRLEN; i++) { + sinp[i] = (short)i; + } + + for (int i = 0; i < ITERS; i++) { + test_float16_float(fout , sinp); + } + } +} diff --git a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java new file mode 100644 index 00000000000..c64b851096d --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** +* @test +* @key randomness +* @summary Test vectorization of numberOfTrailingZeros/numberOfLeadingZeros for Long +* @requires vm.compiler2.enabled +* @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | +* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) +* @library /test/lib / +* @run driver compiler.vectorization.TestNumberOfContinuousZeros +*/ + +package compiler.vectorization; + +import compiler.lib.ir_framework.*; +import java.util.Random; +import jdk.test.lib.Asserts; + +public class TestNumberOfContinuousZeros { + private long[] input; + private int[] output; + private static final int LEN = 1024; + private Random rng; + + public static void main(String args[]) { + TestFramework.run(); + } + + public TestNumberOfContinuousZeros() { + input = new long[LEN]; + output = new int[LEN]; + rng = new Random(42); + for (int i = 0; i < LEN; ++i) { + input[i] = rng.nextLong(); + } + } + + @Test + @IR(counts = {IRNode.COUNTTRAILINGZEROS_VL, "> 0"}) + public void vectorizeNumberOfTrailingZeros() { + for (int i = 0; i < LEN; ++i) { + output[i] = Long.numberOfTrailingZeros(input[i]); + } + } + + @Test + @IR(counts = {IRNode.COUNTLEADINGZEROS_VL, "> 0"}) + public void vectorizeNumberOfLeadingZeros() { + for (int i = 0; i < LEN; ++i) { + output[i] = Long.numberOfLeadingZeros(input[i]); + } + } + + @Run(test = {"vectorizeNumberOfTrailingZeros", "vectorizeNumberOfLeadingZeros"}) + public void checkResult() { + vectorizeNumberOfTrailingZeros(); + for (int i = 0; i < LEN; ++i) { + Asserts.assertEquals(output[i], Long.numberOfTrailingZeros(input[i])); + } + vectorizeNumberOfLeadingZeros(); + for (int i = 0; i < LEN; ++i) { + Asserts.assertEquals(output[i], Long.numberOfLeadingZeros(input[i])); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index b6b2e42ce9b..20912582b7f 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -25,8 +25,8 @@ * @test * @summary Test vectorization of popcount for Long * @requires vm.compiler2.enabled -* @requires vm.cpu.features ~= ".*avx512bw.*" | (vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) -* @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" +* @requires ((os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") & vm.cpu.features ~= ".*avx512bw.*") | +* os.simpleArch == "aarch64" * @library /test/lib / * @run driver compiler.vectorization.TestPopCountVectorLong */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java index fec99f9e749..2d399fbd274 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java @@ -25,8 +25,7 @@ * @bug 8288112 * @summary Auto-vectorization of ReverseBytes operations. * @requires vm.compiler2.enabled - * @requires vm.cpu.features ~= ".*avx2.*" - * @requires os.simpleArch == "x64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" * @library /test/lib / * @run driver compiler.vectorization.TestReverseBytes */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java new file mode 100644 index 00000000000..69e97e5c0ef --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorization; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8297689 + * @summary Test miscompilation of reverseBytes call from subword types + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.vectorization.TestSubwordReverseBytes + */ + +public class TestSubwordReverseBytes { + private static final int SIZE = 32000; + + private static int[] idx = new int[SIZE]; + private static short[] rbs = new short[SIZE]; + private static char[] rbc = new char[SIZE]; + + static { + for (int i = 0; i < SIZE; i++) { + idx[i] = i; + } + for (short s = 0; s < SIZE; s++) { + rbs[s] = Short.reverseBytes(s); + } + for (char c = 0; c < SIZE; c++) { + rbc[c] = Character.reverseBytes(c); + } + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_V}) + public static int[] testShortReverseBytes() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes((short) idx[i]); + } + return res; + } + + @Run(test = "testShortReverseBytes") + public static void testShort() { + int[] res = testShortReverseBytes(); + for (int i = 0; i < SIZE; i++) { + if (res[i] != rbs[i]) { + throw new RuntimeException("Wrong result: expected = " + + (int) rbs[i] + ", actual = " + res[i]); + } + } + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_V}) + public static int[] testCharacterReverseBytes() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes((char) idx[i]); + } + return res; + } + + @Run(test = "testCharacterReverseBytes") + public static void testChar() { + int[] res = testCharacterReverseBytes(); + for (int i = 0; i < SIZE; i++) { + if (res[i] != rbc[i]) { + throw new RuntimeException("Wrong result: expected = " + + (int) rbc[i] + ", actual = " + res[i]); + } + } + } + + public static void main(String[] args) { + TestFramework.run(); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java index a894f7a93cb..ec2119eec21 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java @@ -47,15 +47,18 @@ public class BasicCharOpTest extends VectorizationTestRunner { private char[] a; private char[] b; private char[] c; + private int[] idx; public BasicCharOpTest() { a = new char[SIZE]; b = new char[SIZE]; c = new char[SIZE]; + idx = new int[SIZE]; for (int i = 0; i < SIZE; i++) { a[i] = (char) (20 * i); b[i] = (char) (i + 44444); c[i] = (char) 10000; + idx[i] = i; } } @@ -189,5 +192,24 @@ public char[] vectorUnsignedShiftRight() { } return res; } + + // ------------- ReverseBytes ------------- + @Test + public char[] reverseBytesWithChar() { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes(a[i]); + } + return res; + } + + @Test + public int[] reverseBytesWithInt() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes((char) idx[i]); + } + return res; + } } diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java index 19011325c2e..1dd424499c1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java @@ -47,15 +47,18 @@ public class BasicShortOpTest extends VectorizationTestRunner { private short[] a; private short[] b; private short[] c; + private int[] idx; public BasicShortOpTest() { a = new short[SIZE]; b = new short[SIZE]; c = new short[SIZE]; + idx = new int[SIZE]; for (int i = 0; i < SIZE; i++) { a[i] = (short) (-12 * i); b[i] = (short) (9 * i + 8888); c[i] = (short) -32323; + idx[i] = i; } } @@ -187,5 +190,24 @@ public short[] vectorUnsignedShiftRight() { } return res; } + + // ------------- ReverseBytes ------------- + @Test + public short[] reverseBytesWithShort() { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes(a[i]); + } + return res; + } + + @Test + public int[] reverseBytesWithInt() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes((short) idx[i]); + } + return res; + } } diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index 4356c07747f..aa3a902b30b 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -85,10 +85,14 @@ private static void testMemoryLimitWithSwappiness(String dockerMemLimit, String // capabilities or the cgroup is not mounted. Memory limited without swap." // we only have Memory and Swap Limit is: in the output try { - out.shouldContain("Memory and Swap Limit is: " + expectedReadLimit) - .shouldContain( + if (out.getOutput().contains("memory_and_swap_limit_in_bytes: not supported")) { + System.out.println("memory_and_swap_limit_in_bytes not supported, avoiding Memory and Swap Limit check"); + } else { + out.shouldContain("Memory and Swap Limit is: " + expectedReadLimit) + .shouldContain( "Memory and Swap Limit has been reset to " + expectedResetLimit + " because swappiness is 0") - .shouldContain("Memory & Swap Limit: " + expectedLimit); + .shouldContain("Memory & Swap Limit: " + expectedLimit); + } } catch (RuntimeException ex) { System.out.println("Expected Memory and Swap Limit output missing."); System.out.println("You may need to add 'cgroup_enable=memory swapaccount=1' to the Linux kernel boot parameters."); diff --git a/test/hotspot/jtreg/gc/TestFullGCCount.java b/test/hotspot/jtreg/gc/TestFullGCCount.java index 4557fb95c7b..1c178b755db 100644 --- a/test/hotspot/jtreg/gc/TestFullGCCount.java +++ b/test/hotspot/jtreg/gc/TestFullGCCount.java @@ -29,6 +29,8 @@ * @summary JMM GC counters overcount in some cases * @comment Shenandoah has "ExplicitGCInvokesConcurrent" on by default * @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false) + * @comment G1 has separate counters for STW Full GC and concurrent GC. + * @requires !(vm.gc.G1 & vm.opt.ExplicitGCInvokesConcurrent == true) * @requires vm.gc != "Z" * @modules java.management * @run main/othervm -Xlog:gc gc.TestFullGCCount diff --git a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java index 3fdf50be317..57704252b2f 100644 --- a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java +++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java @@ -96,7 +96,8 @@ public static void main(String[] args) { switch (args[0]) { case "G1": test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}), - new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"})); + new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}), + new GCBeanDescription("G1 Concurrent GC", new String[] {"G1 Old Gen"})); break; case "Parallel": test(new GCBeanDescription("PS Scavenge", new String[] {"PS Eden Space", "PS Survivor Space"}), diff --git a/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java b/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java index d04a1a4374b..616d740cff9 100644 --- a/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java +++ b/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java @@ -50,7 +50,6 @@ public static void main(String[] args) throws Exception { "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc", GCTestWithEvacuationFailure.class.getName()); diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index d0fe28f0bbc..0fa739530c7 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -278,7 +278,6 @@ private void testWithEvacuationFailureLogs() throws Exception { "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc+phases=debug", GCTestWithEvacuationFailure.class.getName()); @@ -291,7 +290,6 @@ private void testWithEvacuationFailureLogs() throws Exception { "-Xmn16M", "-Xms32M", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc+phases=trace", GCTestWithEvacuationFailure.class.getName()); @@ -368,7 +366,7 @@ public static void main(String [] args) { static class GCTestWithConcurrentStart { public static void main(String [] args) { jdk.test.whitebox.WhiteBox WB = jdk.test.whitebox.WhiteBox.getWhiteBox(); - WB.g1StartConcMarkCycle(); + WB.g1StartConcurrentGC(); } } diff --git a/test/hotspot/jtreg/gc/g1/TestHumongousRemsetsMatch.java b/test/hotspot/jtreg/gc/g1/TestHumongousRemsetsMatch.java index 29fea883776..71782982e39 100644 --- a/test/hotspot/jtreg/gc/g1/TestHumongousRemsetsMatch.java +++ b/test/hotspot/jtreg/gc/g1/TestHumongousRemsetsMatch.java @@ -65,12 +65,7 @@ public static void main(String[] args) throws Exception { } wb.fullGC(); - - // Trigger a concurrent cycle and wait until the Remark pause - wb.g1StartConcMarkCycle(); - while (wb.g1InConcurrentMark()) { - Thread.sleep(200); - } + wb.g1RunConcurrentGC(); wb.youngGC(); // Trigger verification error. System.out.println(lotsOfHumongousObjects + " " + alignmentFudge); diff --git a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java index a17d0f41e25..26ba0da396a 100644 --- a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java +++ b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -135,12 +135,7 @@ public static void main(String args[]) throws Exception { // Memory objects have been promoted to old by full GC. // Concurrent cycle may select regions for rebuilding - wb.g1StartConcMarkCycle(); // concurrent-start, remark and cleanup - - // Sleep to make sure concurrent cycle is done - while (wb.g1InConcurrentMark()) { - Thread.sleep(1000); - } + wb.g1RunConcurrentGC(); System.out.println(used); } diff --git a/test/hotspot/jtreg/gc/g1/TestNoEagerReclaimOfHumongousRegions.java b/test/hotspot/jtreg/gc/g1/TestNoEagerReclaimOfHumongousRegions.java index a886a13dd85..0626c544d3c 100644 --- a/test/hotspot/jtreg/gc/g1/TestNoEagerReclaimOfHumongousRegions.java +++ b/test/hotspot/jtreg/gc/g1/TestNoEagerReclaimOfHumongousRegions.java @@ -78,10 +78,7 @@ public static void main(String[] args) throws InterruptedException{ garbageAndRefList.clear(); // Run a concurrent mark cycle to mark all references but the static one as dead. - wb.g1StartConcMarkCycle(); - while (wb.g1InConcurrentMark()) { - Thread.sleep(100); - } + wb.g1RunConcurrentGC(); // Run a young collection to make sure humongous object still can't be eagerly reclaimed. wb.youngGC(); diff --git a/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java new file mode 100644 index 00000000000..688d85d4ffb --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 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 gc.g1; + +/* + * @test + * @bug 8297186 + * @requires vm.gc.G1 + * @library /test/lib + * @run driver gc.g1.TestOneEdenRegionAfterGC + * @summary Test that on a very small heap g1 with very little data (smaller than region size) + * will use at least one eden region after gc to avoid full gcs. + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestOneEdenRegionAfterGC { + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-Xmn" + YoungGenSize, + "-Xmx512M", + "-Xms512M", + "-XX:G1HeapRegionSize=32M", + "-XX:+UseG1GC", + "-Xlog:gc,gc+ergo*=trace", + TestOneEdenRegionAfterGC.Allocate.class.getName(), + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static void main(String args[]) throws Exception { + OutputAnalyzer out = run(); + + out.shouldMatch(".*Pause Young \\(Normal\\).*"); + out.shouldNotMatch(".*Pause Full.*"); + } + + public static class Allocate { + public static Object dummy; + + public static void main(String [] args) throws Exception { + if (args.length != 1) { + throw new IllegalArgumentException("Usage: "); + } + + long youngGenSize = Long.parseLong(args[0]); + triggerYoungGCs(youngGenSize); + } + + public static void triggerYoungGCs(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } + } +} + diff --git a/test/hotspot/jtreg/gc/g1/TestRegionLivenessPrint.java b/test/hotspot/jtreg/gc/g1/TestRegionLivenessPrint.java index 5e9456334f1..035c1dfa3f8 100644 --- a/test/hotspot/jtreg/gc/g1/TestRegionLivenessPrint.java +++ b/test/hotspot/jtreg/gc/g1/TestRegionLivenessPrint.java @@ -44,10 +44,7 @@ public class TestRegionLivenessPrint { public static void main(String[] args) throws InterruptedException { WhiteBox wb = WhiteBox.getWhiteBox(); // Run a concurrent mark cycle to trigger the liveness accounting log messages. - wb.g1StartConcMarkCycle(); - while (wb.g1InConcurrentMark()) { - Thread.sleep(100); - } + wb.g1RunConcurrentGC(); } } diff --git a/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java b/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java new file mode 100644 index 00000000000..524650bba69 --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 gc.g1; + +/* + * @test TestRemarkCleanupMXBean + * @bug 8297247 + * @summary Test that Remark and Cleanup are correctly reported by + * a GarbageCollectorMXBean + * @requires vm.gc.G1 + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @modules java.base/jdk.internal.misc + * java.management + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -XX:+UseG1GC -Xlog:gc + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * gc.g1.TestRemarkCleanupMXBean + */ + +import static jdk.test.whitebox.WhiteBox.getWhiteBox; + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.gc.GC; + +public class TestRemarkCleanupMXBean { + public static void main(String[] args) throws Exception { + GarbageCollectorMXBean g1ConcGCBean = null; + String expectedName = "G1 Concurrent GC"; + for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { + if (expectedName.equals(bean.getName())) { + g1ConcGCBean = bean; + break; + } + } + if (g1ConcGCBean == null) { + throw new RuntimeException("Unable to find GC bean: " + expectedName); + } + + long before = g1ConcGCBean.getCollectionCount(); + getWhiteBox().g1RunConcurrentGC(); + long after = g1ConcGCBean.getCollectionCount(); + + if (after >= before + 2) { // Must report a Remark and a Cleanup + System.out.println(g1ConcGCBean.getName() + " reports a difference " + + after + " - " + before + " = " + (after - before)); + } else { + throw new RuntimeException("Remark or Cleanup not reported by " + + g1ConcGCBean.getName()); + } + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java index 860d3ce48c7..8666c3c3c4a 100644 --- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java +++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java @@ -67,13 +67,7 @@ public static void main(String args[]) throws Exception { // Memory objects have been promoted to old by full GC. // Concurrent cycle should not select any regions for rebuilding - wb.g1StartConcMarkCycle(); // concurrent-start, remark and cleanup - - // Sleep to make sure concurrent cycle is done - while (wb.g1InConcurrentMark()) { - Thread.sleep(1000); - } - + wb.g1RunConcurrentGC(); System.out.println(used); } diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java index 7030b68714e..36c6fd6ce60 100644 --- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java +++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java @@ -125,8 +125,7 @@ private static void testYoungEvacFail() throws Exception { new String[] {"-XX:+G1EvacuationFailureALot", "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC"}); + "-XX:+UnlockDiagnosticVMOptions"}); output.shouldHaveExitValue(0); verifyCollection("Pause Young (Normal)", false, false, true, output.getStdout()); @@ -190,18 +189,18 @@ private static void verifyCollection(String name, boolean expectBefore, boolean Asserts.assertTrue(ci != null, "Expected GC not found: " + name + "\n" + data); // Verify Before - verifyType(ci, expectBefore, VERIFY_BEFORE); + verifyType(ci, expectBefore, VERIFY_BEFORE, data); // Verify During - verifyType(ci, expectDuring, VERIFY_DURING); + verifyType(ci, expectDuring, VERIFY_DURING, data); // Verify After - verifyType(ci, expectAfter, VERIFY_AFTER); + verifyType(ci, expectAfter, VERIFY_AFTER, data); } - private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern) { + private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern, String data) { if (shouldExist) { - Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification pattern " + pattern + " for: " + ci.getName()); + Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification pattern " + pattern + " for: " + ci.getName() + "\n" + data); } else { - Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification pattern " + pattern + " for: " + ci.getName()); + Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification pattern " + pattern + " for: " + ci.getName() + "\n" + data); } } @@ -273,22 +272,26 @@ public static void main(String args[]) throws Exception { partialFree(used); used = alloc1M(); - wb.g1StartConcMarkCycle(); // concurrent-start, remark and cleanup - partialFree(used); - // Sleep to make sure concurrent cycle is done - while (wb.g1InConcurrentMark()) { - Thread.sleep(1000); - } + wb.concurrentGCAcquireControl(); + try { + wb.concurrentGCRunTo(wb.AFTER_MARKING_STARTED); + partialFree(used); - // Trigger two young GCs, first will be young-prepare-mixed, second will be mixed. - used = alloc1M(); - wb.youngGC(); // young-prepare-mixed - partialFree(used); + wb.concurrentGCRunToIdle(); - used = alloc1M(); - wb.youngGC(); // mixed - partialFree(used); + // Trigger two young GCs while preventing a new concurrent GC. + // First will be young-prepare-mixed, second will be mixed. + used = alloc1M(); + wb.youngGC(); // young-prepare-mixed + partialFree(used); + + used = alloc1M(); + wb.youngGC(); // mixed + partialFree(used); + } finally { + wb.concurrentGCReleaseControl(); + } } private static Object[] alloc1M() { diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java index 166772f0a0b..c2be830f57c 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java @@ -126,9 +126,7 @@ public void provoke() { WHITE_BOX.youngGC(); Helpers.waitTillCMCFinished(WHITE_BOX, 0); WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - WHITE_BOX.g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); + WHITE_BOX.g1RunConcurrentGC(); } }, FULL_GC_MEMORY_PRESSURE { diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/TestObjectCollected.java b/test/hotspot/jtreg/gc/g1/humongousObjects/TestObjectCollected.java index 52542738ef4..b1ddecd7290 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/TestObjectCollected.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/TestObjectCollected.java @@ -79,9 +79,7 @@ public void provoke() { CMC { @Override public void provoke() { - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - WHITE_BOX.g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); + WHITE_BOX.g1RunConcurrentGC(); } }, FULL_GC_MEMORY_PRESSURE { diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GC.java b/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GC.java index 66b5ed6e622..3a479612bba 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GC.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GC.java @@ -41,9 +41,7 @@ public enum GC { @Override public Runnable get() { return () -> { - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - WHITE_BOX.g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); + WHITE_BOX.g1RunConcurrentGC(); }; } @@ -67,13 +65,15 @@ public List shouldNotContain() { @Override public Runnable get() { return () -> { - WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - - WHITE_BOX.g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); + WHITE_BOX.concurrentGCAcquireControl(); + try { + WHITE_BOX.youngGC(); + WHITE_BOX.youngGC(); + WHITE_BOX.concurrentGCRunTo(WHITE_BOX.AFTER_MARKING_STARTED); + WHITE_BOX.concurrentGCRunToIdle(); + } finally { + WHITE_BOX.concurrentGCReleaseControl(); + } }; } @@ -141,19 +141,18 @@ public List shouldNotContain() { @Override public Runnable get() { return () -> { - WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - - WHITE_BOX.g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - - WHITE_BOX.youngGC(); - Helpers.waitTillCMCFinished(WHITE_BOX, 0); - // Provoking Mixed GC - WHITE_BOX.youngGC();// second evacuation pause will be mixed - Helpers.waitTillCMCFinished(WHITE_BOX, 0); + WHITE_BOX.concurrentGCAcquireControl(); + try { + WHITE_BOX.youngGC(); + WHITE_BOX.youngGC(); + WHITE_BOX.concurrentGCRunTo(WHITE_BOX.AFTER_MARKING_STARTED); + WHITE_BOX.concurrentGCRunToIdle(); + WHITE_BOX.youngGC(); + // Provoking Mixed GC + WHITE_BOX.youngGC();// second evacuation pause will be mixed + } finally { + WHITE_BOX.concurrentGCReleaseControl(); + } }; } diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GCTokens.java b/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GCTokens.java index b7a26b4aad9..c454127d0e6 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GCTokens.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/objectGraphTest/GCTokens.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -33,7 +33,7 @@ private GCTokens() { public static final String WB_INITIATED_YOUNG_GC = "Young (Normal) (WhiteBox Initiated Young GC)"; public static final String WB_INITIATED_MIXED_GC = "Young (Mixed) (WhiteBox Initiated Young GC)"; - public static final String WB_INITIATED_CMC = "WhiteBox Initiated Concurrent Mark"; + public static final String WB_INITIATED_CMC = "WhiteBox Initiated Run to Breakpoint"; public static final String FULL_GC = "Full (System.gc())"; public static final String FULL_GC_MEMORY_PRESSURE = "WhiteBox Initiated Full GC"; public static final String CMC = "Concurrent Mark)"; diff --git a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java index 91ddd45573d..30553a7b8c6 100644 --- a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java +++ b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -32,10 +32,11 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -XX:CompressedClassSpaceSize=48m gc.metaspace.CompressedClassSpaceSizeInJmapHeap + * @run main/timeout=240 gc.metaspace.CompressedClassSpaceSizeInJmapHeap */ import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.apps.LingeredApp; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.SA.SATestUtils; @@ -49,7 +50,9 @@ public class CompressedClassSpaceSizeInJmapHeap { public static void main(String[] args) throws Exception { SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. - String pid = Long.toString(ProcessTools.getProcessId()); + LingeredApp theApp = new LingeredApp(); + LingeredApp.startApp(theApp, "-XX:CompressedClassSpaceSize=48m"); + String pid = Long.toString(theApp.getPid()); JDKToolLauncher jmap = JDKToolLauncher.create("jhsdb") .addToolArg("jmap") @@ -69,6 +72,8 @@ public static void main(String[] args) throws Exception { OutputAnalyzer output = new OutputAnalyzer(read(out)); output.shouldContain("CompressedClassSpaceSize = 50331648 (48.0MB)"); out.delete(); + + LingeredApp.stopApp(theApp); } private static void run(ProcessBuilder pb) throws Exception { diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index aed3c9350de..25f18134127 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -50,7 +50,7 @@ public class TestLinkToNativeRBP { final static Linker abi = Linker.nativeLinker(); static final SymbolLookup lookup = SymbolLookup.loaderLookup(); - final static MethodHandle foo = abi.downcallHandle(lookup.lookup("foo").get(), + final static MethodHandle foo = abi.downcallHandle(lookup.find("foo").get(), FunctionDescriptor.of(ValueLayout.JAVA_INT)); static int foo() throws Throwable { diff --git a/test/hotspot/jtreg/gc/stress/TestMultiThreadStressRSet.java b/test/hotspot/jtreg/gc/stress/TestMultiThreadStressRSet.java index 99d59fc3b71..4876a0bf1c7 100644 --- a/test/hotspot/jtreg/gc/stress/TestMultiThreadStressRSet.java +++ b/test/hotspot/jtreg/gc/stress/TestMultiThreadStressRSet.java @@ -270,6 +270,9 @@ public void run() { */ private static class Shifter extends Thread { + // Only one thread at a time can be controlling concurrent GC. + static final Object concGCMonitor = new Object(); + static Shifter concGCController = null; final TestMultiThreadStressRSet boss; final int sleepTime; final int shift; @@ -292,9 +295,28 @@ public void run() { objs[j] = null; } } - if (!WB.g1InConcurrentMark()) { + // If no currently controlling thread and no concurrent GC + // in progress, then claim control. + synchronized (concGCMonitor) { + if ((concGCController == null) && !WB.g1InConcurrentMark()) { + concGCController = this; + } + } + if (concGCController == this) { + // If we've claimed control then take control, start a + // concurrent GC, and release control and the claim, + // letting the GC run to completion while we continue + // doing work. System.out.println("%% start CMC"); - WB.g1StartConcMarkCycle(); + WB.concurrentGCAcquireControl(); + try { + WB.concurrentGCRunTo(WB.AFTER_MARKING_STARTED, false); + } finally { + WB.concurrentGCReleaseControl(); + synchronized (concGCMonitor) { + concGCController = null; + } + } } else { System.out.println("%% CMC is already in progress"); } diff --git a/test/hotspot/jtreg/gc/stress/TestStressRSetCoarsening.java b/test/hotspot/jtreg/gc/stress/TestStressRSetCoarsening.java index d5fc8a10342..2930990a3db 100644 --- a/test/hotspot/jtreg/gc/stress/TestStressRSetCoarsening.java +++ b/test/hotspot/jtreg/gc/stress/TestStressRSetCoarsening.java @@ -293,10 +293,7 @@ public void go() throws InterruptedException { if (pre > cur) { // Number of references went down. // Need to provoke recalculation of RSet. - WB.g1StartConcMarkCycle(); - while (WB.g1InConcurrentMark()) { - Thread.sleep(1); - } + WB.g1RunConcurrentGC(false); } // To force the use of rememebered set entries we need to provoke a GC. diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java index 728155a23c0..f0f93676251 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java @@ -104,6 +104,10 @@ public void handleNotification(Notification n, Object o) { if ("end of GC cycle".equals(info.getGcAction())) { gcCount++; } + } else if (info.getGcName().startsWith("G1")) { + if ("end of minor GC".equals(info.getGcAction())) { + gcCount++; + } } else { gcCount++; } diff --git a/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java b/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java index 664ff403d97..3ddc1287b20 100644 --- a/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java +++ b/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -73,13 +73,12 @@ public static void allocateOldObjects( } /** - * Provoke at least one mixed gc by starting a marking cycle, waiting for its end and triggering two GCs. + * Provoke at least one mixed gc by performing a concurrent collection + * and triggering two GCs. * @param liveOldObjects The objects supposed to survive this marking cycle. */ public static void provokeMixedGC(List liveOldObjects) { - Helpers.waitTillCMCFinished(getWhiteBox(), 10); - getWhiteBox().g1StartConcMarkCycle(); - Helpers.waitTillCMCFinished(getWhiteBox(), 10); + getWhiteBox().g1RunConcurrentGC(); getWhiteBox().youngGC(); // the "Prepare Mixed" gc getWhiteBox().youngGC(); // the "Mixed" gc diff --git a/test/hotspot/jtreg/gc/whitebox/TestConcMarkCycleWB.java b/test/hotspot/jtreg/gc/whitebox/TestConcMarkCycleWB.java deleted file mode 100644 index b99f8901800..00000000000 --- a/test/hotspot/jtreg/gc/whitebox/TestConcMarkCycleWB.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, 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 gc.whitebox; - -/* - * @test TestConMarkCycleWB - * @bug 8065579 - * @requires vm.gc.G1 - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.compiler - * java.management - * jdk.internal.jvmstat/sun.jvmstat.monitor - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC gc.whitebox.TestConcMarkCycleWB - * @summary Verifies that ConcurrentMarking-related WB works properly - */ -import static jdk.test.lib.Asserts.assertTrue; -import jdk.test.whitebox.WhiteBox; - -public class TestConcMarkCycleWB { - - public static void main(String[] args) throws Exception { - WhiteBox wb = WhiteBox.getWhiteBox(); - - wb.youngGC(); - assertTrue(wb.g1StartConcMarkCycle()); - while (wb.g1InConcurrentMark()) { - Thread.sleep(5); - } - - wb.fullGC(); - assertTrue(wb.g1StartConcMarkCycle()); - while (wb.g1InConcurrentMark()) { - Thread.sleep(5); - } - assertTrue(wb.g1StartConcMarkCycle()); - } -} diff --git a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java index 01921182353..d380419632c 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java +++ b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java @@ -42,7 +42,7 @@ public class ClassFileVersionTest { * compilation. If a particular class becomes non-preview, any * currently preview class can be substituted in. */ - private static final Class PREVIEW_API = java.lang.foreign.MemoryAddress.class; + private static final Class PREVIEW_API = java.lang.foreign.MemorySegment.class; static Method m; public static void testIt(String className, int expectedResult) throws Exception { @@ -77,11 +77,11 @@ public static void main(String argv[]) throws Throwable { // test primitive array. should return latest version. int ver = (int)m.invoke((new int[3]).getClass()); - if (ver != 64) { + if (ver != latestMajor) { int got_minor = (ver >> 16) & LOWER_16; int got_major = ver & LOWER_16; throw new RuntimeException( - "Expected 0:64, but got " + got_minor + ":" + got_major + " for primitive array"); + "Expected 0:" + latestMajor + ", but got " + got_minor + ":" + got_major + " for primitive array"); } // test object array. should return class file version of component. diff --git a/test/hotspot/jtreg/runtime/ClassUnload/UnloadTestWithVerifyDuringGC.java b/test/hotspot/jtreg/runtime/ClassUnload/UnloadTestWithVerifyDuringGC.java index 8de4fcc9942..f21abadc999 100644 --- a/test/hotspot/jtreg/runtime/ClassUnload/UnloadTestWithVerifyDuringGC.java +++ b/test/hotspot/jtreg/runtime/ClassUnload/UnloadTestWithVerifyDuringGC.java @@ -50,23 +50,9 @@ public class UnloadTestWithVerifyDuringGC { private static final WhiteBox wb = WhiteBox.getWhiteBox(); - private static void waitUntilConcMarkFinished() throws Exception { - while (wb.g1InConcurrentMark()) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - System.out.println("Got InterruptedException while waiting for concurrent mark to finish"); - throw e; - } - } - } - private static void triggerUnloadingWithConcurrentMark() throws Exception { - // Try to unload classes using concurrent mark. First wait for any currently running concurrent - // cycle. - waitUntilConcMarkFinished(); - wb.g1StartConcMarkCycle(); - waitUntilConcMarkFinished(); + // Try to unload classes using concurrent mark. + wb.g1RunConcurrentGC(); } private static String className = "test.Empty"; diff --git a/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java b/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java index 7c45e2ea02f..65ae6b16081 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java +++ b/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java @@ -30,6 +30,15 @@ * @run main/othervm PrintClasses */ +/* + * @test + * @bug 8298162 + * @summary Test jcmd VM.classes with JFR + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm -XX:StartFlightRecording PrintClasses + */ + import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.JDKToolFinder; diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index 1544e18c9d2..0029304f9de 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -61,7 +61,6 @@ public class VMDeprecatedOptions { {"InitialRAMFraction", "64"}, {"TLABStats", "false"}, {"AllowRedefinitionToAddDeleteMethods", "true"}, - {"EnableWaitForParallelLoad", "false"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java index 8e2033e7329..d336d8c227a 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java @@ -126,7 +126,7 @@ public static void largeHeapAbove32GTest() throws Exception { if (testNarrowKlassBase()) { if (!(Platform.isAArch64() && Platform.isOSX())) { // see JDK-8262895 output.shouldContain("Narrow klass base: 0x0000000000000000"); - if (!Platform.isAArch64() && !Platform.isOSX()) { + if (!Platform.isAArch64() && !Platform.isPPC() && !Platform.isOSX()) { output.shouldContain("Narrow klass shift: 0"); } } diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java index 59325adc9f8..2a3ddd808e9 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java @@ -25,21 +25,28 @@ /* * @test - * @bug 8065895 - * @summary Synchronous signals during error reporting may terminate or hang VM process + * @summary Check secondary error handling * @library /test/lib * @requires vm.debug * @requires os.family != "windows" - * @author Thomas Stuefe (SAP) * @modules java.base/jdk.internal.misc * java.management - * @run driver SecondaryErrorTest + * @run driver SecondaryErrorTest no_callstacks + */ + +/* + * @test + * @summary Check secondary error handling + * @library /test/lib + * @requires vm.debug + * @requires os.family != "windows" + * @modules java.base/jdk.internal.misc + * java.management + * @run driver SecondaryErrorTest with_callstacks */ -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.regex.Pattern; import jdk.test.lib.process.OutputAnalyzer; @@ -49,12 +56,35 @@ public class SecondaryErrorTest { public static void main(String[] args) throws Exception { + + boolean with_callstacks = false; + if (args.length != 1) { + throw new IllegalArgumentException("Missing argument"); + } else if (args[0].equals("with_callstacks")) { + with_callstacks = true; + } else if (args[0].equals("no_callstacks")) { + with_callstacks = false; + } else { + throw new IllegalArgumentException("unknown argument (" + args[0] + ")"); + } + + // How this works: + // The test will fault with SIGFPE (ErrorHandlerTest=15) and then, during error handling, + // fault twice with SIGSEGV (TestCrashInErrorHandler=14). The point is not only to test + // secondary crashes, but secondary crashes with a *different* error signal. This should + // be handled correctly and not hang/end the process (so the signal mask must be set correctly). + // See JDK-8065895. + // We do this twice, to check that secondary signal handling works repeatedly. + // We also check, optionally, that +ErrorLogSecondaryErrorDetails produces callstacks for + // the secondary error. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-Xmx100M", "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=15", "-XX:TestCrashInErrorHandler=14", + "-XX:" + (with_callstacks ? "+" : "-") + "ErrorLogSecondaryErrorDetails", "-version"); OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); @@ -72,12 +102,23 @@ public static void main(String[] args) throws Exception { // which is an end marker written in the last step and proves that hs-err file was // completely written. - Pattern [] pattern = new Pattern[] { - Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)..."), - Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 1\\).*\\]"), - Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)..."), - Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 2\\).*\\]"), - }; + ArrayList patternlist = new ArrayList<>(); + patternlist.add(Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)...")); + patternlist.add(Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 1\\).*\\]")); + if (with_callstacks) { + patternlist.add(Pattern.compile("\\[siginfo:.*\\(SIGSEGV\\).*\\]")); + patternlist.add(Pattern.compile("\\[stack: Native frames:.*")); + patternlist.add(Pattern.compile(".*VMError::controlled_crash.*")); + } + // and again, to see that repeated error reporting steps work + patternlist.add(Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)...")); + patternlist.add(Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 2\\).*\\]")); + if (with_callstacks) { + patternlist.add(Pattern.compile("\\[siginfo:.*\\(SIGSEGV\\).*\\]")); + patternlist.add(Pattern.compile("\\[stack: Native frames:.*")); + patternlist.add(Pattern.compile(".*VMError::controlled_crash.*")); + } + Pattern[] pattern = patternlist.toArray(new Pattern[] {}); HsErrFileUtils.checkHsErrFileContent(hs_err_file, pattern, false); diff --git a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java index bc889564004..1cfa6ff5dff 100644 --- a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java @@ -33,7 +33,8 @@ * @requires vm.flagless * @requires vm.flavor != "zero" * @library /test/lib - * @run driver/timeout=180000 SyncOnValueBasedClassTest + * @enablePreview + * @run main/othervm/timeout=180000 --enable-preview SyncOnValueBasedClassTest */ public class SyncOnValueBasedClassTest { @@ -62,7 +63,7 @@ private static void initTestObjects() { private static void generateTests() { initTestObjects(); - String[] commonFatalTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", "-XX:DiagnoseSyncOnValueBasedClasses=1"}; + String[] commonFatalTestsFlags = {"--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", "-XX:DiagnoseSyncOnValueBasedClasses=1"}; fatalTests = new String[specificFlags.length * testObjects.size()][]; for (int i = 0; i < specificFlags.length; i++) { for (int j = 0; j < testObjects.size(); j++) { @@ -72,7 +73,7 @@ private static void generateTests() { .toArray(String[]::new); } } - String[] commonLogTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:DiagnoseSyncOnValueBasedClasses=2"}; + String[] commonLogTestsFlags = {"--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:DiagnoseSyncOnValueBasedClasses=2"}; logTests = new String[specificFlags.length][]; for (int i = 0; i < specificFlags.length; i++) { logTests[i] = Stream.of(commonLogTestsFlags, specificFlags[i], new String[] {"SyncOnValueBasedClassTest$LogTest"}) @@ -96,6 +97,7 @@ public static void main(String[] args) throws Exception { output.shouldHaveExitValue(0); checkOutput(output); } + virtualThreadTests(); } private static void checkOutput(OutputAnalyzer output) { @@ -163,4 +165,36 @@ public void run() { } } } + + // Very basic sanity tests to show things work for virtual threads too. + private static void virtualThreadTests() throws Exception { + final String[] vtTest = { "--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", + "", "SyncOnValueBasedClassTest$VTTest" }; + // Fatal test + vtTest[3] = "-XX:DiagnoseSyncOnValueBasedClasses=1"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vtTest); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldContain("fatal error: Synchronizing on object"); + output.shouldNotContain("synchronization on value based class did not fail"); + output.shouldNotHaveExitValue(0); + + // Log test + vtTest[3] = "-XX:DiagnoseSyncOnValueBasedClasses=2"; + pb = ProcessTools.createJavaProcessBuilder(vtTest); + output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); + output.shouldContain("Synchronizing on object"); + output.shouldContain("synchronization on value based class did not fail"); + } + + static class VTTest { + public static void main(String[] args) throws Exception { + var thread = Thread.ofVirtual().start(() -> { + synchronized (Character.valueOf('H')) { + System.out.println("synchronization on value based class did not fail"); + } + }); + thread.join(); + } + } } diff --git a/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java b/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java index 099836a12e9..e9576c24faf 100644 --- a/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java +++ b/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java @@ -64,8 +64,8 @@ public static void main(String args[]) throws Exception { long totalCommitted = 0, totalReserved = 0; long totalCommittedSum = 0, totalReservedSum = 0; - // Match '- (reserved=KB, committed=KB) - Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match '- (reserved=KB, committed=KB) and some times readonly=KB + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB((,\\sreadonly=(?\\d+)KB)|)\\)"); // Match 'Total: reserved=KB, committed=KB' Pattern totalMemoryPattern = Pattern.compile("Total\\:\\sreserved=(?\\d+)KB,\\scommitted=(?\\d+)KB"); @@ -85,6 +85,16 @@ public static void main(String args[]) throws Exception { long typeCommitted = Long.parseLong(typeMatcher.group("committed")); long typeReserved = Long.parseLong(typeMatcher.group("reserved")); + // Only Shared class space has readonly component + if (lines[i].contains("Shared class space") && typeMatcher.group("readonly") != null) { + long typeReadOnly = Long.parseLong(typeMatcher.group("readonly")); + // Make sure readonly is always less or equal to committed + if (typeReadOnly > typeCommitted) { + throwTestException("Readonly (" + typeReadOnly + ") was more than Committed (" + + typeCommitted + ") for mtType: " + typeMatcher.group("typename")); + } + } + // Make sure reserved is always less or equals if (typeCommitted > typeReserved) { throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java index 0f71c1ba389..1c2431d7c81 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java @@ -48,6 +48,7 @@ public static void main(String[] args) throws Exception { opts.addSuffix("ALL-SYSTEM"); opts.addSuffix("-Xlog:hashtables"); opts.addSuffix("-Xmx500m"); + opts.addSuffix("-XX:MetaspaceSize=500M"); // avoid heap fragmentation by avoiding metaspace-limit induced GCs opts.addSuffix("-Xlog:gc+region+cds"); opts.addSuffix("-Xlog:cds=debug"); // test detailed metadata info printing diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java index 493ac9937e9..f53defc2903 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java @@ -42,6 +42,7 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.ArrayList; @@ -357,6 +358,8 @@ private static void patchJarForDynamicDump(String cp) throws Exception { if (n > 0) { firstJar = firstJar.substring(0, n); } + // get the real path in case the firstJar is specified as a relative path + firstJar = Paths.get(firstJar).toRealPath().toString(); String classDir = System.getProperty("test.classes"); String expected = getOutputDir() + File.separator; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java b/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java index 9ade2fc4900..20cc0426dd1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java @@ -33,6 +33,9 @@ */ import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.helpers.ClassFileInstaller; @@ -44,10 +47,26 @@ public static void main(String[] args) throws Exception { String mismatchMsg = "shared class paths mismatch"; String hintMsg = "(hint: enable -Xlog:class+path=info to diagnose the failure)"; + // Dump CDS archive with hello.jar + // Run with a jar file that differs from the original jar file by the first character only: -cp mello.jar + // Shared class paths mismatch should be detected. + String hellojar = "hello.jar"; + String mellojar = "mello.jar"; + Files.copy(Paths.get(appJar), Paths.get(hellojar), StandardCopyOption.COPY_ATTRIBUTES); + Files.copy(Paths.get(appJar), Paths.get(mellojar), StandardCopyOption.COPY_ATTRIBUTES); + TestCommon.testDump(hellojar, TestCommon.list("Hello")); + TestCommon.run("-cp", mellojar, + "-Xlog:cds", + "Hello") + .assertAbnormalExit(unableToUseMsg, mismatchMsg, hintMsg); + // Dump an archive with a specified JAR file in -classpath TestCommon.testDump(appJar, TestCommon.list("Hello")); // Then try to execute the archive without -classpath -- it should fail + // To run without classpath, set the property test.noclasspath to true + // so that ProcessTools won't append the classpath of the jtreg process to the test process + System.setProperty("test.noclasspath", "true"); TestCommon.run( /* "-cp", appJar, */ // <- uncomment this and the execution should succeed "-Xlog:cds", @@ -70,6 +89,7 @@ public static void main(String[] args) throws Exception { .shouldContain(mismatchMsg) .shouldNotContain(hintMsg); }); + System.clearProperty("test.noclasspath"); // Dump CDS archive with 2 jars: -cp hello.jar:jar2.jar // Run with 2 jars but the second jar doesn't exist: -cp hello.jarjar2.jarx diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java index 16b46c505bd..4107a9508e4 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java @@ -96,6 +96,8 @@ public static void main(String[] args) throws Exception { /* dump xmx */ /* run xmx */ /* dump base */ /* run base */ 128 * M, 128 * M, default_base, default_base + 256L * 1024 * 1024, 128 * M, 16376 * M, 0x0000000119200000L, -1, + 16 * M * 1024, 6 * M * 1024, default_base, 0x90000000, + 128 * M, 128 * M, 0xf0000000, 0xe0000000 }; for (int i = 0; i < bases.length; i += 4) { diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java b/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java index c64b21c7d1b..36c48a7fd19 100644 --- a/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java +++ b/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 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 @@ -24,9 +25,11 @@ /** * @test TestPrimitiveArrayCriticalWithBadParam - * @bug 8269697 + * @bug 8269697 8292674 * @summary -Xcheck:jni should catch wrong parameter passed to GetPrimitiveArrayCritical + * @comment Tests reporting with regular thread and virtual thread. * @library /test/lib + * @enablePreview * @run main/native TestPrimitiveArrayCriticalWithBadParam */ import java.util.List; @@ -47,39 +50,54 @@ public class TestPrimitiveArrayCriticalWithBadParam { public static void main(String[] args) { if (args.length > 0) { - test(); + test(args[0]); } else { - runTest(); + runTest(false); + runTest(true); } } - private static void runTest() { + private static void runTest(boolean useVThread) { List pbArgs = new ArrayList<>(); pbArgs.add("-XX:-CreateCoredumpOnCrash"); pbArgs.add("-Xcheck:jni"); + pbArgs.add("--enable-preview"); pbArgs.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH); pbArgs.add(TestPrimitiveArrayCriticalWithBadParam.class.getName()); - pbArgs.add("test"); + pbArgs.add(useVThread ? "vtest" : "test"); try { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(pbArgs.toArray(new String[0])); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); // -Xcheck:jni should warn the bad parameter analyzer.shouldContain("FATAL ERROR in native method: Primitive type array expected but not received for JNI array operation"); + analyzer.shouldContain("TestPrimitiveArrayCriticalWithBadParam.pin"); analyzer.shouldNotHaveExitValue(0); } catch (IOException e) { throw new RuntimeException(e); } } - private static void test() { - Object[] objs = new Object[10]; - for (int i = 0; i < objs.length; i++) { - objs[i] = new MyClass(); + private static void test(String mode) { + Runnable r = () -> { + Object[] objs = new Object[10]; + for (int i = 0; i < objs.length; i++) { + objs[i] = new MyClass(); + } + pin(objs); + System.out.println("Object array pinned"); + unpin(objs); + }; + if (mode.equals("vtest")) { + Thread t = Thread.ofVirtual().start(r); + try { + t.join(); + } catch (InterruptedException ex) { + throw new Error("unexpected", ex); + } + } else { + r.run(); } - pin(objs); - System.out.println("Object array pinned"); - unpin(objs); } public static class MyClass { public Object ref = new Object(); diff --git a/test/hotspot/jtreg/runtime/jni/nativeStack/TestNativeStack.java b/test/hotspot/jtreg/runtime/jni/nativeStack/TestNativeStack.java new file mode 100644 index 00000000000..36880fe256c --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/nativeStack/TestNativeStack.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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 8295974 + * @requires os.family != "windows" + * @library /test/lib + * @summary Generate a JNI Fatal error, or a warning, in a launched VM and check + * the native stack is present as expected. + * @comment The native code only supports POSIX so no windows testing + * @run driver TestNativeStack + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestNativeStack { + + /** + * Create a native thread that will execute native code that + * will either trigger a JNI warning (with -Xcheck:jni) or a JNI + * error, depending on the value of `warning`. + */ + static native void triggerJNIStackTrace(boolean warning); + + static { + System.loadLibrary("nativeStack"); + } + + public static void main(String[] args) throws Throwable { + // case 1: Trigger a JNI warning with Xcheck:jni + OutputAnalyzer oa = + ProcessTools.executeTestJvm("-Xcheck:jni", + "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, + "TestNativeStack$Main"); + oa.shouldHaveExitValue(0); + oa.shouldContain("WARNING in native method"); + oa.shouldContain("thread_start"); + oa.reportDiagnosticSummary(); + + // Case 2: Trigger a JNI FatalError call + oa = ProcessTools.executeTestJvm("-XX:-CreateCoredumpOnCrash", + "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, + "TestNativeStack$Main", + "error"); + oa.shouldNotHaveExitValue(0); + oa.shouldContain("FATAL ERROR in native method"); + oa.shouldContain("thread_start"); + oa.reportDiagnosticSummary(); + } + + static class Main { + public static void main(String[] args) throws Throwable { + boolean doWarning = args.length == 0; + System.out.println("Triggering a JNI " + + (doWarning ? "warning" : "fatal error")); + triggerJNIStackTrace(doWarning); + } + } +} diff --git a/test/hotspot/jtreg/runtime/jni/nativeStack/libnativeStack.c b/test/hotspot/jtreg/runtime/jni/nativeStack/libnativeStack.c new file mode 100644 index 00000000000..c8b9c9a999e --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/nativeStack/libnativeStack.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 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. + */ + +#include +#include + +#include +#include + +#include "jni.h" + +JavaVM* jvm; +jboolean warning = 0; + +void generateWarning(JNIEnv *env) { + jclass class_id; + jmethodID method_id; + + printf("About to trigger JNI Warning\n"); + + // Just call Thread.currentThread() twice in succession without checking + // for an exception in between. + + class_id = (*env)->FindClass (env, "java/lang/Thread"); + if (class_id == NULL) { + fprintf(stderr, "Test ERROR. Can't load class Thread\n"); + exit(1); + } + + method_id = (*env)->GetStaticMethodID(env, class_id, "currentThread", + "()Ljava/lang/Thread;"); + if (method_id == NULL) { + fprintf(stderr, "Test ERROR. Can't find method currentThread\n"); + exit(1); + } + + jobject nativeThread = (*env)->CallStaticObjectMethod(env, class_id, method_id, NULL); + nativeThread = (*env)->CallStaticObjectMethod(env, class_id, method_id, NULL); +} + +void generateError(JNIEnv *env) { + printf("About to trigger JNI FatalError\n"); + (*env)->FatalError(env, "Fatal error generated in test code"); +} + +static void * thread_start(void* unused) { + JNIEnv *env; + int res; + + printf("Native thread is running and attaching as daemon ...\n"); + + res = (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&env, NULL); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't attach current thread: %d\n", res); + exit(1); + } + + if (warning != 0) { + generateWarning(env); + } else { + generateError(env); + } + + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + exit(1); + } + printf("Native thread terminating\n"); + + return NULL; +} + +JNIEXPORT void JNICALL +Java_TestNativeStack_triggerJNIStackTrace +(JNIEnv *env, jclass cls, jboolean warn) { + pthread_t thread; + int res = (*env)->GetJavaVM(env, &jvm); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't extract JavaVM: %d\n", res); + exit(1); + } + + warning = warn; + + if ((res = pthread_create(&thread, NULL, thread_start, NULL)) != 0) { + fprintf(stderr, "TEST ERROR: pthread_create failed: %s (%d)\n", strerror(res), res); + exit(1); + } + + if ((res = pthread_join(thread, NULL)) != 0) { + fprintf(stderr, "TEST ERROR: pthread_join failed: %s (%d)\n", strerror(res), res); + exit(1); + } +} diff --git a/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldArray.jasm b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldArray.jasm new file mode 100644 index 00000000000..50be8b01ba2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldArray.jasm @@ -0,0 +1,49 @@ +/* + * 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. + */ + +/* +public class NoSuchFieldArray { + static char[] z; + public NoSuchFieldArray() { + z = new char[1]; + } +} +*/ + +super public class NoSuchFieldArray + version 65:0 +{ + // REMOVED static Field z:"[C"; + + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + iconst_1; + newarray char; + putstatic Field z:"[C"; + return; + } + +} // end Class NoSuchFieldArray diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldMultiArray.jasm similarity index 64% rename from test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java rename to test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldMultiArray.jasm index 822493619cb..1ad49ac7e5b 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java +++ b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldMultiArray.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,21 +21,30 @@ * questions. */ -package org.reactivestreams.tck.flow.support; +/* +public class NoSuchFieldMultiArray { + static double[][] a; + public NoSuchFieldMultiArray() { + a = new double[1][1]; + } +} +*/ -public final class SubscriberBufferOverflowException extends RuntimeException { - public SubscriberBufferOverflowException() { - } +super public class NoSuchFieldMultiArray + version 65:0 +{ + // REMOVED static Field a:"[[D"; - public SubscriberBufferOverflowException(String message) { - super(message); + public Method "":"()V" + stack 2 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + iconst_1; + iconst_1; + multianewarray class "[[D", 2; + putstatic Field a:"[[D"; + return; } - public SubscriberBufferOverflowException(String message, Throwable cause) { - super(message, cause); - } - - public SubscriberBufferOverflowException(Throwable cause) { - super(cause); - } -} +} // end Class NoSuchFieldMultiArray diff --git a/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldOutputTest.java b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldOutputTest.java new file mode 100644 index 00000000000..90d11da4804 --- /dev/null +++ b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldOutputTest.java @@ -0,0 +1,108 @@ +/* + * 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 + * @bug 8298065 + * @summary Test output of NoSuchFieldError when field signature does not match + * @compile NoSuchFieldPrimitive.jasm NoSuchFieldReference.jasm TestClass.java + * @compile NoSuchFieldArray.jasm NoSuchFieldMultiArray.jasm + * @run main NoSuchFieldOutputTest + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +// Tests the output text of NoSuchFieldError +public class NoSuchFieldOutputTest { + + public static void main(java.lang.String[] unused) throws Exception { + try { + Class.forName("NoSuchFieldPrimitive").newInstance(); + } catch (NoSuchFieldError nsfe) { + testNoSuchFieldOutput(nsfe, "primitive"); + } + try { + Class.forName("NoSuchFieldReference").newInstance(); + } catch (NoSuchFieldError nsfe) { + testNoSuchFieldOutput(nsfe, "reference"); + } + try { + Class.forName("NoSuchFieldArray").newInstance(); + } catch (NoSuchFieldError nsfe) { + testNoSuchFieldOutput(nsfe, "array"); + } + try { + Class.forName("NoSuchFieldMultiArray").newInstance(); + } catch (NoSuchFieldError nsfe) { + testNoSuchFieldOutput(nsfe, "multiArray"); + } + } + + private static void testNoSuchFieldOutput(NoSuchFieldError nsfe, String testType) throws Exception { + Pattern noSuchFieldPattern = Pattern.compile("Class (?[\\w\\d]+) does not have member field '(?[\\S]+) (?[\\w\\d]+)'"); + String output = nsfe.getMessage(); + Matcher noSuchFieldMatcher = noSuchFieldPattern.matcher(output); + if (noSuchFieldMatcher.matches()) { + switch (testType) { + case "primitive": + checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldPrimitive", "int", "x"); + break; + case "reference": + checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldReference", "TestClass", "y"); + break; + case "array": + checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldArray", "char[]", "z"); + break; + case "multiArray": + checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldMultiArray", "double[][]", "a"); + break; + default: + throwTestException("No matching test", output); + } + } else { + throwTestException("Output format does not match", output); + } + System.out.println(output); + } + + private static void checkOutputGroups(Matcher noSuchFieldMatcher, String output, + String testClass, String testSig, String testVar) throws Exception { + String classname = noSuchFieldMatcher.group("classname"); + String signature = noSuchFieldMatcher.group("signature"); + String varname = noSuchFieldMatcher.group("varname"); + if (!classname.equals(testClass)) { + throwTestException("Failed to match class name", output); + } + if (!signature.equals(testSig)) { + throwTestException("Failed to match type signature", output); + } + if (!varname.equals(testVar)) { + throwTestException("Failed to match field name", output); + } + } + + private static void throwTestException(String reason, String output) throws Exception { + throw new Exception(reason + " . Stdout is :\n" + output); + } +} diff --git a/src/hotspot/share/metaprogramming/isArray.hpp b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldPrimitive.jasm similarity index 67% rename from src/hotspot/share/metaprogramming/isArray.hpp rename to test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldPrimitive.jasm index 10040ccdf4d..532951fb50d 100644 --- a/src/hotspot/share/metaprogramming/isArray.hpp +++ b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldPrimitive.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -19,17 +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_METAPROGRAMMING_ISARRAY_HPP -#define SHARE_METAPROGRAMMING_ISARRAY_HPP - -#include "metaprogramming/integralConstant.hpp" +/* +public class NoSuchFieldPrimitive { + // static int x; + public NoSuchFieldPrimitive() { + x = 123; + } +} +*/ -template struct IsArray: public FalseType {}; +super public class NoSuchFieldPrimitive + version 65:0 +{ + // REMOVED static Field x:I; -template struct IsArray: public TrueType {}; -template struct IsArray: public TrueType {}; + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + bipush 123; + putstatic Field x:"I"; + return; + } -#endif // SHARE_METAPROGRAMMING_ISARRAY_HPP +} // end Class NoSuchFieldPrimitive diff --git a/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldReference.jasm b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldReference.jasm new file mode 100644 index 00000000000..b7fb1320b14 --- /dev/null +++ b/test/hotspot/jtreg/runtime/linkResolver/NoSuchFieldReference.jasm @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* +public class NoSuchFieldReference { + static TestClass y; + public NoSuchFieldReference() { + y = new TestClass(); + } +} +*/ + +super public class NoSuchFieldReference + version 65:0 +{ + // REMOVED static Field y:"LTestClass;"; + + public Method "":"()V" + stack 2 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + new class TestClass; + dup; + invokespecial Method TestClass."":"()V"; + putstatic Field y:"LTestClass;"; + return; + } + +} // end Class NoSuchFieldReference diff --git a/test/hotspot/jtreg/runtime/linkResolver/TestClass.java b/test/hotspot/jtreg/runtime/linkResolver/TestClass.java new file mode 100644 index 00000000000..170427431e0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/linkResolver/TestClass.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// Used as a reference type for a field in NoSuchFieldReference.jasm +public class TestClass {} diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java b/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java index 5a88fcc5b25..922cad26735 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java @@ -61,7 +61,7 @@ public static void main(String args[]) throws Exception { // Test GetFrameCount on virtual live thread Thread vThread = Thread.ofVirtual().name("VirtualThread-Live").start(() -> { - checkFrames(Thread.currentThread(), false, 9); + checkFrames(Thread.currentThread(), false, 10); }); vThread.join(); @@ -79,13 +79,13 @@ public static void main(String args[]) throws Exception { } // this is too fragile, implementation can change at any time. - checkFrames(vThread1, false, 14); + checkFrames(vThread1, false, 15); LockSupport.unpark(vThread1); vThread1.join(); // Test GetFrameCount on live platform thread Thread pThread = Thread.ofPlatform().name("PlatformThread-Live").start(() -> { - checkFrames(Thread.currentThread(), false, 5); + checkFrames(Thread.currentThread(), false, 6); }); pThread.join(); @@ -101,7 +101,7 @@ public static void main(String args[]) throws Exception { while(pThread1.getState() != Thread.State.WAITING) { Thread.sleep(1); } - checkFrames(pThread1, false, 5); + checkFrames(pThread1, false, 6); LockSupport.unpark(pThread1); pThread1.join(); @@ -118,10 +118,11 @@ class FixedDepthThread implements Runnable { Object checkFlag; Thread thread; - // Each stack has 2 frames additional to expected depth + // Each stack has 3 frames additional to expected depth // 0: FixedDepthThread: run()V // 1: java/lang/Thread: run()V - static final int ADDITIONAL_STACK_COUNT = 2; + // 2: java/lang/Thread: runWith()V + static final int ADDITIONAL_STACK_COUNT = 3; private FixedDepthThread(String name, int depth, Object checkFlag) { this.thread = Thread.ofPlatform().name(name).unstarted(this); diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp index 1e3b6211400..deb494dd0aa 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp @@ -36,7 +36,8 @@ static frame_info expected_virtual_frames[] = { {"LGetStackTraceCurrentThreadTest;", "dummy", "()V"}, {"LGetStackTraceCurrentThreadTest;", "chain", "()V"}, {"LTask;", "run", "()V"}, - {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"} + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, }; static frame_info expected_platform_frames[] = { @@ -44,7 +45,8 @@ static frame_info expected_platform_frames[] = { {"LGetStackTraceCurrentThreadTest;", "dummy", "()V"}, {"LGetStackTraceCurrentThreadTest;", "chain", "()V"}, {"LTask;", "run", "()V"}, - {"Ljava/lang/Thread;", "run", "()V"} + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/Thread;", "run", "()V"}, }; JNIEXPORT jint JNICALL diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp index 1f1bce5bb01..2b1c2385491 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp @@ -35,7 +35,8 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr03;", "dummy", "()V"}, {"Lgetstacktr03;", "chain", "()V"}, {"Lgetstacktr03$Task;", "run", "()V"}, - {"Ljava/lang/Thread;", "run", "()V"} + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/Thread;", "run", "()V"}, }; static frame_info expected_virtual_frames[] = { @@ -43,6 +44,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr03;", "dummy", "()V"}, {"Lgetstacktr03;", "chain", "()V"}, {"Lgetstacktr03$Task;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda$31.0x0000000800098810;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp index d15c4112757..873522ab531 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp @@ -38,6 +38,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr04$TestThread;", "chain2", "()V"}, {"Lgetstacktr04$TestThread;", "chain1", "()V"}, {"Lgetstacktr04$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -48,6 +49,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr04$TestThread;", "chain2", "()V"}, {"Lgetstacktr04$TestThread;", "chain1", "()V"}, {"Lgetstacktr04$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp index 3e228886538..d4d4b2447ab 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp @@ -39,6 +39,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr05$TestThread;", "chain2", "()V"}, {"Lgetstacktr05$TestThread;", "chain1", "()V"}, {"Lgetstacktr05$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -48,6 +49,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr05$TestThread;", "chain2", "()V"}, {"Lgetstacktr05$TestThread;", "chain1", "()V"}, {"Lgetstacktr05$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp index 21568a64226..0fd52c697f4 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp @@ -43,6 +43,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr06$TestThread;", "chain2", "()V"}, {"Lgetstacktr06$TestThread;", "chain1", "()V"}, {"Lgetstacktr06$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -52,6 +53,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr06$TestThread;", "chain2", "()V"}, {"Lgetstacktr06$TestThread;", "chain1", "()V"}, {"Lgetstacktr06$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp index 7bf22883f55..a422fc0782f 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp @@ -45,6 +45,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr07$TestThread;", "chain2", "()V"}, {"Lgetstacktr07$TestThread;", "chain1", "()V"}, {"Lgetstacktr07$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -55,6 +56,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr07$TestThread;", "chain2", "()V"}, {"Lgetstacktr07$TestThread;", "chain1", "()V"}, {"Lgetstacktr07$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp index af71c61b0c4..977bbf00b04 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp @@ -44,6 +44,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr08$TestThread;", "chain2", "()V"}, {"Lgetstacktr08$TestThread;", "chain1", "()V"}, {"Lgetstacktr08$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -56,6 +57,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr08$TestThread;", "chain2", "()V"}, {"Lgetstacktr08$TestThread;", "chain1", "()V"}, {"Lgetstacktr08$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java index 2ed557f8e94..884f521a02f 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java @@ -56,7 +56,7 @@ public static void main(String[] args) throws Exception { "field InstanceKlass _constants ConstantPool*", "field Klass _name Symbol*", "field JavaThread _osthread OSThread*", - "field TenuredGeneration _the_space ContiguousSpace*", + "field TenuredGeneration _the_space TenuredSpace*", "field VirtualSpace _low_boundary char*", "field MethodCounters _backedge_counter InvocationCounter", "field nmethod _entry_bci int", diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java index 49f90f7f9fd..4ba76034276 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -101,12 +101,18 @@ private static void testWithPid(final boolean useRmiPort, final boolean useRegis int registryPort = REGISTRY_DEFAULT_PORT; if (useRegistryPort) { registryPort = Utils.findUnreservedFreePort(REGISTRY_DEFAULT_PORT); + if (registryPort == -1) { + throw new RuntimeException("Cannot find a registryPort, findUnreservedFreePort returns -1"); + } jhsdbLauncher.addToolArg("--registryport"); jhsdbLauncher.addToolArg(Integer.toString(registryPort)); } final int rmiPort = useRmiPort ? Utils.findUnreservedFreePort(REGISTRY_DEFAULT_PORT, registryPort) : -1; if (useRmiPort) { + if (rmiPort == -1) { + throw new RuntimeException("Cannot find an rmiPort, findUnreservedFreePort returns -1"); + } jhsdbLauncher.addToolArg("--rmiport"); jhsdbLauncher.addToolArg(Integer.toString(rmiPort)); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java index ac3ab653fa9..d725958ff65 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -266,7 +266,7 @@ private void testRun() for (int i = 0; ; i++) { vm.resume(); - breakpointForCommunication(); + breakpointForCommunication(debuggeeName); int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java index 86a8e1faa5e..d7a1bbc7833 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -292,7 +292,7 @@ private void testRun() for (int i = 0; ; i++) { - breakpointForCommunication(); + breakpointForCommunication(debuggeeName); int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java index 9256f28003e..d14b635c39f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -45,7 +45,7 @@ * com.sun.jdi.ObjectReference.setValue() * properly throws IllegalArgumentException when a * debugger part of the test attempts to set value of - * debuggee's static field which is declared as final.
    + * debuggee's final field. */ public class setvalue004 { static final String DEBUGGEE_CLASS = @@ -62,8 +62,8 @@ public class setvalue004 { static final String COMMAND_READY = "ready"; static final String COMMAND_QUIT = "quit"; - static final int FLDS_NUM = 9; static final String DEBUGGEE_FLDS[] = { + // static final fields "sByteFld", "sShortFld", "sIntFld", @@ -72,7 +72,17 @@ public class setvalue004 { "sDoubleFld", "sCharFld", "sBooleanFld", - "sStrFld" + "sStrFld", + // instance final fields + "iByteFld", + "iShortFld", + "iIntFld", + "iLongFld", + "iFloatFld", + "iDoubleFld", + "iCharFld", + "iBooleanFld", + "iStrFld" }; private Log log; @@ -141,16 +151,16 @@ private int runIt(String args[], PrintStream out) { rType = objRef.referenceType(); // provoke the IllegalArgumentException - for (int i=0; i setupLaunchingConnector(LaunchingConnecto vmArgs = vmUserArgs; } - /* Need --enable-preview on the debuggee in order to support virtual threads. */ boolean vthreadMode = "Virtual".equals(System.getProperty("main.wrapper")); if (vthreadMode) { + /* Need --enable-preview on the debuggee in order to support virtual threads. */ vmArgs += " --enable-preview"; + /* Some tests need more carrier threads than the default provided. */ + vmArgs += " -Djdk.virtualThreadScheduler.parallelism=15"; } /* diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index 8a5f37a5c05..fe569a3b5d1 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -23,7 +23,7 @@ modules=java.xml groups=TEST.groups # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/XMLSchema.xsd b/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/XMLSchema.xsd index 2e9a2729ec5..1efc31dec3a 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/XMLSchema.xsd +++ b/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/XMLSchema.xsd @@ -647,7 +647,7 @@ - The element element can be used either + The element can be used either at the top level to define an element-type binding globally, or within a content model to either reference a globally-defined element or type or declare an element-type binding locally. diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index 076d247637b..0cc1034440e 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 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 @@ -27,3 +27,4 @@ # ############################################################################# +jdk/internal/vm/Continuation/Fuzz.java#default 8298058 generic-x64 diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 1c6bc65b894..617e72c5fe3 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -1,6 +1,6 @@ ########################################################################### # -# Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 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 @@ -119,6 +119,7 @@ java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generi java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all +java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java 8296972 macosx-all java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all java/awt/FileDialog/FileDialogIconTest/FileDialogIconTest.java 8160558 windows-all @@ -186,6 +187,7 @@ java/awt/Focus/6981400/Test1.java 8029675 windows-all,macosx-all java/awt/Focus/6981400/Test3.java 8173264 generic-all java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474,8224055 macosx-all,windows-all +java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java 8298910 linux-all java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java 8194947 generic-all java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all @@ -220,7 +222,6 @@ java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 linux-all java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all -sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java 8284825 windows-all sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all @@ -416,7 +417,6 @@ java/awt/image/VolatileImage/GradientPaints.java 8199003 linux-all java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882 linux-all -java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java 8202931 macosx-all,linux-all java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all,linux-all java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all @@ -425,7 +425,6 @@ java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.j java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all -java/awt/Toolkit/DesktopProperties/rfe4758438.java 8193547 linux-all java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163 java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all @@ -474,8 +473,8 @@ java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all # jdk_foreign -java/foreign/TestUpcallStack.java 8275584 macosx-aarch64 -java/foreign/TestDowncallStack.java 8275584 macosx-aarch64 +java/foreign/callarranger/TestAarch64CallArranger.java generic-x86 +java/foreign/TestLargeSegmentCopy.java generic-x86 ############################################################################ @@ -586,7 +585,12 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic- sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all -javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 +javax/net/ssl/SSLEngine/TestAllSuites.java 8298874 generic-all +javax/net/ssl/SSLEngine/IllegalRecordVersion.java 8298873 generic-all +javax/net/ssl/SSLEngine/EngineCloseOnAlert.java 8298868 generic-all +javax/net/ssl/SSLEngine/ConnectionTest.java 8298869 generic-all +javax/net/ssl/SSLEngine/CheckStatus.java 8298872 generic-all +javax/net/ssl/SSLEngine/Basics.java 8298867 generic-all sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all @@ -607,7 +611,6 @@ com/sun/security/sasl/gsskerb/AuthOnly.java 8039280 generic- com/sun/security/sasl/gsskerb/ConfSecurityLayer.java 8039280 generic-all com/sun/security/sasl/gsskerb/NoSecurityLayer.java 8039280 generic-all sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 generic-all -sun/security/provider/PolicyParser/ExtDirsChange.java 8039280 generic-all sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all sun/security/tools/keytool/NssTest.java 8295343 linux-all @@ -617,6 +620,8 @@ sun/security/pkcs11/rsa/TestKeyPairGenerator.java 8295343 linux-al sun/security/pkcs11/rsa/TestKeyFactory.java 8295343 linux-all sun/security/pkcs11/KeyStore/Basic.java 8295343 linux-all +java/security/Policy/Root/Root.java 8299994 generic-all + ############################################################################ # jdk_sound @@ -649,27 +654,29 @@ javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java 802462 # The next test below is an intermittent failure javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all javax/swing/JTree/4633594/JTreeFocusTest.java 7105441 macosx-all -javax/swing/JSpinner/4788637/bug4788637.java 8296084 linux-all javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-all javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8198003 generic-all javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all javax/swing/JTabbedPane/8007563/Test8007563.java 8051591 generic-all javax/swing/JTabbedPane/4624207/bug4624207.java 8064922 macosx-all javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all -javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java 8194048 windows-all -javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java 8213562 linux-all javax/swing/JFileChooser/6798062/bug6798062.java 8146446 windows-all javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all +javax/swing/JRadioButton/4314194/bug4314194.java 8298153 linux-all # Several tests which fail on some hidpi systems/macosx12-aarch64 system java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 -java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8297296 macosx-all +java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8298823 macosx-all javax/swing/JFileChooser/8046391/bug8046391.java 8293862 windows-x64 +javax/swing/JFileChooser/4847375/bug4847375.java 8293862 windows-x64 +java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392 windows-x64 +java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8294264 windows-x64 +java/awt/Mixing/AWT_Mixing/ViewportOverlapping.java 8253184,8295813 windows-x64 sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001 linux-all sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all @@ -711,6 +718,8 @@ com/sun/jdi/AfterThreadDeathTest.java 8232839 linux-al java/util/Locale/LocaleProvidersRun.java 8268379 macosx-x64 sun/util/locale/provider/CalendarDataRegression.java 8268379 macosx-x64 +java/util/concurrent/forkjoin/AsyncShutdownNow.java 8286352 linux-all,windows-x64 +java/util/concurrent/ExecutorService/CloseTest.java 8288899 macosx-aarch64 ############################################################################ @@ -749,7 +758,6 @@ jdk/jfr/startupargs/TestStartName.java 8214685 windows- jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 -jdk/jfr/api/consumer/TestRecordingFileWrite.java 8287699 generic-all ############################################################################ diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 13f0d6249ad..2dbf5cd7822 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -71,7 +71,7 @@ requires.properties= \ jdk.containerized # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 86c24a3c91c..b4e13624d24 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -126,6 +126,7 @@ jdk_util = \ jdk_util_other = \ java/util \ sun/util \ + jdk/internal/util \ -:jdk_collections \ -:jdk_concurrent \ -:jdk_stream @@ -623,9 +624,6 @@ jdk_core_manual_no_input_security = \ com/sun/security/sasl/gsskerb/ConfSecurityLayer.java \ com/sun/security/sasl/gsskerb/NoSecurityLayer.java \ sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java \ - sun/security/provider/PolicyParser/ExtDirs.java \ - sun/security/provider/PolicyParser/ExtDirsChange.java \ - sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java \ sun/security/provider/PolicyParser/PrincipalExpansionError.java \ sun/security/smartcardio/TestChannel.java \ sun/security/smartcardio/TestConnect.java \ diff --git a/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java index 3e7ecbad62e..dba3dcdacef 100644 --- a/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java +++ b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java @@ -26,6 +26,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Random; import javax.crypto.spec.SecretKeySpec; @@ -36,7 +37,7 @@ public class Poly1305IntrinsicFuzzTest { public static void main(String[] args) throws Exception { //Note: it might be useful to increase this number during development of new Poly1305 intrinsics - final int repeat = 100; + final int repeat = 1000; for (int i = 0; i < repeat; i++) { run(); } @@ -44,7 +45,7 @@ public static void main(String[] args) throws Exception { } public static void run() throws Exception { - java.util.Random rnd = new java.util.Random(); + Random rnd = new Random(); long seed = rnd.nextLong(); rnd.setSeed(seed); @@ -52,6 +53,7 @@ public static void run() throws Exception { rnd.nextBytes(key); int msgLen = rnd.nextInt(128, 4096); // x86_64 intrinsic requires 256 bytes minimum byte[] message = new byte[msgLen]; + rnd.nextBytes(message); Poly1305 authenticator = new Poly1305(); Poly1305 authenticatorSlow = new Poly1305(); @@ -62,20 +64,22 @@ public static void run() throws Exception { authenticator.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null); authenticatorSlow.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null); - if (rnd.nextBoolean()) { + if (rnd.nextBoolean() && message.length > 16) { // Prime just the buffer and/or accumulator (buffer can keep at most 16 bytes from previous engineUpdate) - int initDataLen = rnd.nextInt(8, 24); - authenticator.engineUpdate(message, 0, initDataLen); - slowUpdate(authenticatorSlow, message, 0, initDataLen); + int initDataLen = rnd.nextInt(1, 16); + int initDataOffset = rnd.nextInt(0, message.length - initDataLen); + fastUpdate(authenticator, rnd, message, initDataOffset, initDataLen); + slowUpdate(authenticatorSlow, message, initDataOffset, initDataLen); } if (rnd.nextBoolean()) { // Multiple calls to engineUpdate - authenticator.engineUpdate(message, 0, message.length); - slowUpdate(authenticatorSlow, message, 0, message.length); + int initDataOffset = rnd.nextInt(0, message.length); + fastUpdate(authenticator, rnd, message, initDataOffset, message.length - initDataOffset); + slowUpdate(authenticatorSlow, message, initDataOffset, message.length - initDataOffset); } - authenticator.engineUpdate(message, 0, message.length); + fastUpdate(authenticator, rnd, message, 0, message.length); slowUpdate(authenticatorSlow, message, 0, message.length); byte[] tag = authenticator.engineDoFinal(); @@ -87,9 +91,34 @@ public static void run() throws Exception { } static void slowUpdate(Poly1305 authenticator, byte[] message, int offset, int len) { - len = Math.min(message.length, offset + len); - for (int i = offset; i < len; i++) { + for (int i = offset; i < offset + len; i++) { authenticator.engineUpdate(message[i]); } } + + static void fastUpdate(Poly1305 authenticator, Random rnd, byte[] message, int offset, int len) { + ByteBuffer buf; + switch(rnd.nextInt(4)) { + case 0: // byte[] + authenticator.engineUpdate(message, offset, len); + break; + case 1: // ByteArray with backing array + buf = ByteBuffer.wrap(message, offset, len) + .order(java.nio.ByteOrder.LITTLE_ENDIAN); + authenticator.engineUpdate(buf); + break; + case 2: // ByteArray with backing array (non-zero position) + buf = ByteBuffer.wrap(message, 0, len+offset) + .order(java.nio.ByteOrder.LITTLE_ENDIAN) + .position(offset); + authenticator.engineUpdate(buf); + break; + case 3: // ByteArray without backing array (wont be sent to intrinsic) + buf = ByteBuffer.wrap(message, offset, len) + .asReadOnlyBuffer() + .order(java.nio.ByteOrder.LITTLE_ENDIAN); + authenticator.engineUpdate(buf); + break; + } + } } diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java b/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java new file mode 100644 index 00000000000..0aa52aa84c9 --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 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 4912623 + * @key headful + * @requires (os.family == "linux") + * @summary Verifies if all files or folders are selected on CTRL+A press for + * JFileChooser. + * @run main TestFileChooserCtrlASelection + */ + +import java.awt.BorderLayout; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.Point; +import java.awt.Robot; +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class TestFileChooserCtrlASelection { + private static JFrame frame; + private static JFileChooser fileChooser; + private static Robot robot; + private static File testDir; + private static File testFile; + private static File[] SubDirs; + private static File[] subFiles; + private static boolean passed_1 = false; + private static boolean passed_2 = false; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + robot = new Robot(); + robot.setAutoDelay(100); + try { + // create test directory + String tmpDir = System.getProperty("user.home"); + + // Create a test directory that contains only folders + testDir = new File(tmpDir, "testDir"); + if (!testDir.exists()) { + testDir.mkdir(); + } + testDir.deleteOnExit(); + + // create sub directories inside test directory + SubDirs = new File[5]; + for (int i = 0; i < 5; ++i) { + SubDirs[i] = new File(testDir, "subDir_" + (i+1)); + SubDirs[i].mkdir(); + SubDirs[i].deleteOnExit(); + } + + // Create a test directory that contains only files + testFile = new File(tmpDir, "testFile"); + if (!testFile.exists()) { + testFile.mkdir(); + } + testFile.deleteOnExit(); + + // create temporary files inside testFile + subFiles = new File[5]; + for (int i = 0; i < 5; ++i) { + subFiles[i] = File.createTempFile("subFiles_" + (i+1), + ".txt", new File(testFile.getAbsolutePath())); + subFiles[i].deleteOnExit(); + } + } catch (Exception e) { + e.printStackTrace(); + } + doTesting(); + } + + private static void doTesting() throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + createAndShowUI(); + }); + robot.delay(1000); + checkMultiSelectionDefault(); + checkMultiSelectionDisabled(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new JFrame("Test File Chooser Ctrl+A Action"); + frame.getContentPane().setLayout(new BorderLayout()); + fileChooser = new JFileChooser(testDir); + fileChooser.setControlButtonsAreShown(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + frame.getContentPane().add(fileChooser, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + /* + * JFileChooser MultiSelection property is set true by default. + */ + private static void checkMultiSelectionDefault() { + System.out.println("Testing MultiSelection enabled by default"); + Point frameLocation = fileChooser.getLocationOnScreen(); + int frameHeight = frame.getHeight(); + + // check Ctrl+A on folders list + doMouseClick(frameLocation, frameHeight, 50); + doKeyPressAction(); + File files[] = fileChooser.getSelectedFiles(); + System.out.println("files length: " + files.length); + if (files.length > 1) { + passed_1 = true; + } + + // check Ctrl+A on files list + fileChooser.setCurrentDirectory(testFile); + doMouseClick(frameLocation, frameHeight, 230); + doKeyPressAction(); + files = fileChooser.getSelectedFiles(); + System.out.println("files length: " + files.length); + if (files.length > 1) { + passed_2 = true; + } + + if (passed_1 && passed_2) { + System.out.println("Passed"); + } else { + throw new RuntimeException("Unable to select all files " + + "or folder"); + } + } + + private static void checkMultiSelectionDisabled() { + System.out.println("Testing MultiSelection disabled"); + passed_1 = false; + passed_2 = false; + fileChooser.setMultiSelectionEnabled(false); + fileChooser.setCurrentDirectory(testDir); + Point frameLocation = fileChooser.getLocationOnScreen(); + int frameHeight = frame.getHeight(); + + // check Ctrl+A on folders list + doMouseClick(frameLocation, frameHeight, 50); + doKeyPressAction(); + File files[] = fileChooser.getSelectedFiles(); + System.out.println("files length: " + files.length); + if (files.length == 0) { + passed_1 = true; + } + + // check Ctrl+A on files list + fileChooser.setCurrentDirectory(testFile); + doMouseClick(frameLocation, frameHeight, 230); + doKeyPressAction(); + files = fileChooser.getSelectedFiles(); + System.out.println("files length: " + files.length); + if (files.length == 0) { + passed_2 = true; + } + + if (passed_1 && passed_2) { + System.out.println("Passed"); + } else { + throw new RuntimeException("All files or folder selected for" + + "MultiSelection disabled"); + } + } + + private static void doMouseClick(Point frameLocation, int frameHeight, + int offset) { + robot.mouseMove(frameLocation.x + offset, frameLocation.y + + frameHeight / 3); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + } + + private static void doKeyPressAction() { + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.delay(100); + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserOpenSaveButtonText.java b/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserOpenSaveButtonText.java new file mode 100644 index 00000000000..be9417875c0 --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/gtk/TestFileChooserOpenSaveButtonText.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 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 8081507 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @requires (os.family == "linux") + * @summary Verifies if Open/Save button shows text as Open/Save. + * @run main/manual TestFileChooserOpenSaveButtonText + */ + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class TestFileChooserOpenSaveButtonText { + private static JFrame frame; + private static final String INSTRUCTIONS = + "Instructions: \n\n" + + "1. Check the text on button in bottom panel is Open.\n" + + "2. Press Cancel button.\n" + + "3. Check the text on button in bottom panel is Save.\n" + + "4. Press Cancel button.\n" + + "5. If above instructions are confirmed, " + + "Press Pass else Fail."; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + PassFailJFrame passFailJFrame = new PassFailJFrame( + "JFileChooser Test Instructions", INSTRUCTIONS, 5, 8, 35); + try { + SwingUtilities.invokeAndWait( + TestFileChooserOpenSaveButtonText::createAndShowUI); + passFailJFrame.awaitAndCheck(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new JFrame("Test File Chooser Open/Save button text"); + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow( + frame, PassFailJFrame.Position.HORIZONTAL); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.showOpenDialog(null); + fileChooser.showSaveDialog(null); + } +} diff --git a/test/jdk/com/sun/jdi/ArgumentValuesTest.java b/test/jdk/com/sun/jdi/ArgumentValuesTest.java index bcce51bc562..5bae42c4e28 100644 --- a/test/jdk/com/sun/jdi/ArgumentValuesTest.java +++ b/test/jdk/com/sun/jdi/ArgumentValuesTest.java @@ -227,7 +227,7 @@ protected void runTests() } } - // a method with with one generic param + // a method with one generic param { System.out.println("----- Testing generic args"); bpe = resumeTo("ArgumentValuesTarg", GENERIC_ARGS_LINE_1); diff --git a/test/jdk/com/sun/jdi/JdbLastErrorTest.java b/test/jdk/com/sun/jdi/JdbLastErrorTest.java index c5eceb855e1..9cde54207a3 100644 --- a/test/jdk/com/sun/jdi/JdbLastErrorTest.java +++ b/test/jdk/com/sun/jdi/JdbLastErrorTest.java @@ -54,10 +54,10 @@ private static void testWindows() throws Throwable { System.loadLibrary("Kernel32"); SymbolLookup lookup = SymbolLookup.loaderLookup(); MethodHandle getLastError = linker.downcallHandle( - lookup.lookup("GetLastError").orElseThrow(), + lookup.find("GetLastError").orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_INT)); MethodHandle setLastError = linker.downcallHandle( - lookup.lookup("SetLastError").orElseThrow(), + lookup.find("SetLastError").orElseThrow(), FunctionDescriptor.ofVoid(ValueLayout.JAVA_INT)); for (int i = 0; i < 10; i++) { diff --git a/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java b/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java index a726e19192f..5a6ca80573d 100644 --- a/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java +++ b/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java @@ -25,7 +25,7 @@ * @bug 4287596 * @summary Unit test for "Pluggable Connectors and Transports" feature. * - * When a transport service is deployed the virtual machine machine + * When a transport service is deployed the virtual machine * is required to create an AttachingConnector and ListeningConnector * to encapsulate the transport. This tests that the connectors are * created and that they have an "address" argument. diff --git a/test/jdk/com/sun/jdi/lib/jdb/Jdb.java b/test/jdk/com/sun/jdi/lib/jdb/Jdb.java index 0c7c84c521f..73ab885dbf9 100644 --- a/test/jdk/com/sun/jdi/lib/jdb/Jdb.java +++ b/test/jdk/com/sun/jdi/lib/jdb/Jdb.java @@ -152,7 +152,7 @@ public void shutdown() { # # 5) ^main[89] > @ # - # i.e., the > prompt comes out AFTER the prompt we we need to wait for. + # i.e., the > prompt comes out AFTER the prompt we need to wait for. */ // compile regexp once private final static String promptPattern = "?\\[[1-9][0-9]*\\] [ >]*$"; diff --git a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java index ec05aa9ed15..fd73024df6d 100644 --- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java +++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -29,7 +29,11 @@ * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false * @modules java.management/sun.management * jdk.management - * @run main/othervm -Xms64m -Xmx64m GarbageCollectionNotificationContentTest + * @library /test/lib /test/hotspot/jtreg + * @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 + * -Xms64m -Xmx64m GarbageCollectionNotificationContentTest */ import java.util.*; @@ -42,12 +46,14 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.reflect.Field; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.gc.GC; public class GarbageCollectionNotificationContentTest { private static HashMap listenerInvoked = new HashMap(); - static volatile long count = 0; - static volatile long number = 0; + static volatile long notificationReceivedCount = 0; + static volatile long numberOfGCMBeans = 0; static Object synchronizer = new Object(); static class GcListener implements NotificationListener { @@ -58,12 +64,12 @@ public void handleNotification(Notification notif, Object handback) { GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData()); String source = ((ObjectName)notif.getSource()).getCanonicalName(); synchronized(synchronizer) { - if(listenerInvoked.get(source) == null) { - listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),gcNotif); - count++; - if(count >= number) { - synchronizer.notify(); - } + if (listenerInvoked.get(source) == null) { + listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(), gcNotif); + notificationReceivedCount++; + if (notificationReceivedCount >= numberOfGCMBeans) { + synchronizer.notify(); + } } } } @@ -79,16 +85,14 @@ public static void main(String[] args) throws Exception { System.out.println("GC Notification not supported by the JVM, test skipped"); return; } - final ObjectName gcMXBeanPattern = - new ObjectName("java.lang:type=GarbageCollector,*"); - Set names = - mbs.queryNames(gcMXBeanPattern, null); + final ObjectName gcMXBeanPattern = new ObjectName("java.lang:type=GarbageCollector,*"); + Set names = mbs.queryNames(gcMXBeanPattern, null); if (names.isEmpty()) throw new Exception("Test incorrect: no GC MXBeans"); - number = names.size(); + numberOfGCMBeans = names.size(); for (ObjectName n : names) { - if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) { - listenerInvoked.put(n.getCanonicalName(),null); + if (mbs.isInstanceOf(n, "javax.management.NotificationEmitter")) { + listenerInvoked.put(n.getCanonicalName(), null); GcListener listener = new GcListener(); mbs.addNotificationListener(n, listener, null, null); } @@ -100,9 +104,13 @@ public static void main(String[] args) throws Exception { for(int i = 0; i<10000000; i++) { data[i%32] = new int[8]; } + // Trigger G1's concurrent mark + if (GC.G1.isSelected()) { + WhiteBox.getWhiteBox().g1RunConcurrentGC(); + } int wakeup = 0; synchronized(synchronizer) { - while(count != number) { + while(notificationReceivedCount != numberOfGCMBeans) { synchronizer.wait(10000); wakeup++; if(wakeup > 10) @@ -116,9 +124,9 @@ public static void main(String[] args) throws Exception { } private static void checkGarbageCollectionNotificationInfoContent(GarbageCollectionNotificationInfo notif) throws Exception { - System.out.println("GC notification for "+notif.getGcName()); - System.out.print("Action: "+notif.getGcAction()); - System.out.println(" Cause: "+notif.getGcCause()); + System.out.println("GC notification for " + notif.getGcName()); + System.out.print("Action: " + notif.getGcAction()); + System.out.println(" Cause: " + notif.getGcCause()); GcInfo info = notif.getGcInfo(); System.out.print("GC Info #" + info.getId()); System.out.print(" start:" + info.getStartTime()); @@ -126,6 +134,12 @@ private static void checkGarbageCollectionNotificationInfoContent(GarbageCollect System.out.println(" (" + info.getDuration() + "ms)"); Map usage = info.getMemoryUsageBeforeGc(); + // Check MemoryUsage is present. For all but No GC events, check Eden usage decreases: + boolean doCheckMemoryUsage = true; + if (notif.getGcCause().equals("No GC")) { + System.out.println("(skip memory usage check for event with 'No GC' cause)"); + doCheckMemoryUsage = false; + } List pnames = new ArrayList(); for (Map.Entry entry : usage.entrySet() ) { String poolname = (String) entry.getKey(); @@ -133,22 +147,22 @@ private static void checkGarbageCollectionNotificationInfoContent(GarbageCollect MemoryUsage busage = (MemoryUsage) entry.getValue(); MemoryUsage ausage = (MemoryUsage) info.getMemoryUsageAfterGc().get(poolname); if (ausage == null) { - throw new RuntimeException("After Gc Memory does not exist" + - " for " + poolname); + throw new RuntimeException("After Gc Memory does not exist for " + poolname); } System.out.println("Usage for pool " + poolname); System.out.println(" Before GC: " + busage); System.out.println(" After GC: " + ausage); - checkMemoryUsage(poolname, busage, ausage); + if (doCheckMemoryUsage) { + checkMemoryUsage(poolname, busage, ausage); + } } // check if memory usage for all memory pools are returned List pools = ManagementFactory.getMemoryPoolMXBeans(); for (MemoryPoolMXBean p : pools ) { if (!pnames.contains(p.getName())) { - throw new RuntimeException("GcInfo does not contain " + - "memory usage for pool " + p.getName()); + throw new RuntimeException("GcInfo does not contain memory usage for pool " + p.getName()); } } } diff --git a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java index 5c42827eb4d..8ffbdc3e995 100644 --- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java +++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -29,7 +29,11 @@ * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false * @modules java.management/sun.management * jdk.management - * @run main/othervm GarbageCollectionNotificationTest + * @library /test/lib /test/hotspot/jtreg + * @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 + * GarbageCollectionNotificationTest */ import java.util.*; @@ -42,6 +46,8 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.reflect.Field; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.gc.GC; public class GarbageCollectionNotificationTest { private static HashMap listenerInvoked = new HashMap(); @@ -99,6 +105,10 @@ public static void main(String[] args) throws Exception { for(int i = 0; i<100000000; i++) { data[i%32] = new int[8]; } + // Trigger G1's concurrent mark + if (GC.G1.isSelected()) { + WhiteBox.getWhiteBox().g1RunConcurrentGC(); + } int wakeup = 0; synchronized(synchronizer) { while(count != number) { diff --git a/test/jdk/java/awt/AlphaComposite/WindowAlphaCompositeTest.java b/test/jdk/java/awt/AlphaComposite/WindowAlphaCompositeTest.java index 733a68305d3..0ab8b74f3a9 100644 --- a/test/jdk/java/awt/AlphaComposite/WindowAlphaCompositeTest.java +++ b/test/jdk/java/awt/AlphaComposite/WindowAlphaCompositeTest.java @@ -25,7 +25,7 @@ /** * @test * @key headful - * @bug 8266079 + * @bug 8266079 8298887 * @summary [macosx] window rendering alpha composite test * @author Alexey Ushakov * @run main WindowAlphaCompositeTest diff --git a/test/jdk/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java b/test/jdk/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java index 37396a79fa4..229b0492f24 100644 --- a/test/jdk/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java +++ b/test/jdk/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -33,6 +33,10 @@ import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.InputEvent; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; /** * @test @@ -44,6 +48,7 @@ public final class ChoicePopupLocation { private static final int SIZE = 350; private static int frameWidth; + private static Rectangle bounds; public static void main(final String[] args) throws Exception { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); @@ -52,7 +57,7 @@ public static void main(final String[] args) throws Exception { Point right = null; for (GraphicsDevice sd : sds) { GraphicsConfiguration gc = sd.getDefaultConfiguration(); - Rectangle bounds = gc.getBounds(); + bounds = gc.getBounds(); if (left == null || left.x > bounds.x) { left = new Point(bounds.x, bounds.y + bounds.height / 2); } @@ -120,6 +125,8 @@ private static void openPopup(final Choice choice) throws Exception { robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.waitForIdle(); if (choice.getSelectedIndex() == 0) { + BufferedImage failImage = robot.createScreenCapture(bounds); + ImageIO.write(failImage, "png", new File("failImage.png")); throw new RuntimeException(); } } diff --git a/test/jdk/java/awt/Component/ComponentRedrawnTest.java b/test/jdk/java/awt/Component/ComponentRedrawnTest.java new file mode 100644 index 00000000000..6007d23b741 --- /dev/null +++ b/test/jdk/java/awt/Component/ComponentRedrawnTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016, 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 + * @key headful + * @bug 8139581 + * @summary Verify that components are redrawn after + * removal and addition to a container + * @run main ComponentRedrawnTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.swing.JButton; + +public class ComponentRedrawnTest { + + private static Frame frame; + private static Panel componentPanel; + private static Button buttonRemove; + private static Button buttonAdd; + private static Button awtButton; + + private static volatile Robot robot; + private static volatile int x; + private static volatile int y; + private static AtomicInteger awtPainted = new AtomicInteger(); + private static AtomicInteger swingPainted = new AtomicInteger(); + + public static void main(String args[]) throws Exception { + try { + EventQueue.invokeAndWait(() -> createGUI()); + runTest(); + System.out.println("Test Passed"); + } finally { + EventQueue.invokeAndWait(() -> dispose()); + } + } + + private static void createGUI() { + frame = new Frame("ComponentRedrawnTest"); + frame.setSize(350, 300); + frame.setBackground(Color.red); + + componentPanel = new Panel(); + componentPanel.setLayout(null); + componentPanel.setBackground(Color.green); + + awtButton = new Button("AWT Button") { + @Override + public void paint(Graphics g) { + super.paint(g); + awtPainted.incrementAndGet(); + } + }; + + awtButton.setBounds(0, 0, 330, 100); + componentPanel.add(awtButton); + + JButton swingButton = new JButton("Swing JButton") { + @Override + public void paint(Graphics g) { + super.paint(g); + swingPainted.incrementAndGet(); + } + }; + + swingButton.setBounds(0, 100, 330, 100); + componentPanel.add(swingButton); + frame.add(componentPanel, BorderLayout.CENTER); + buttonRemove = new Button("remove"); + buttonRemove.addActionListener(ae -> buttonClicked(ae)); + + buttonAdd = new Button("add"); + buttonAdd.addActionListener(ae -> buttonClicked(ae)); + + Panel controlPanel = new Panel(); + controlPanel.setLayout(new BorderLayout()); + controlPanel.add(buttonRemove, BorderLayout.NORTH); + controlPanel.add(buttonAdd, BorderLayout.SOUTH); + + frame.add(controlPanel, BorderLayout.SOUTH); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void buttonClicked(ActionEvent ae) { + if (ae.getSource() == buttonRemove) { + frame.remove(componentPanel); + } else if (ae.getSource() == buttonAdd) { + frame.add(componentPanel); + } + frame.invalidate(); + frame.validate(); + } + + private static void runTest() throws Exception { + EventQueue.invokeAndWait(() -> createGUI()); + robot = new Robot(); + robot.setAutoDelay(500); + awtPainted.set(0); + swingPainted.set(0); + + try { + EventQueue.invokeAndWait(() -> { + x = awtButton.getLocationOnScreen().x + + awtButton.getSize().width / 2; + y = awtButton.getLocationOnScreen().y + + awtButton.getSize().height / 2; + }); + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + try { + EventQueue.invokeAndWait(() -> { + x = buttonRemove.getLocationOnScreen().x + + buttonRemove.getSize().width / 2; + y = buttonRemove.getLocationOnScreen().y + + buttonRemove.getSize().height / 2; + }); + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + try { + EventQueue.invokeAndWait(() -> { + x = buttonAdd.getLocationOnScreen().x + + buttonAdd.getSize().width / 2; + y = buttonAdd.getLocationOnScreen().y + + buttonAdd.getSize().height / 2; + }); + + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + if (awtPainted.get() == 0) { + throw new RuntimeException("AWT button is not painted"); + } + if (swingPainted.get() == 0) { + throw new RuntimeException("Swing button is not painted"); + } + } + + private static void dispose() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/java/awt/Dialog/ModalDialogTest/ModalDialogTest.java b/test/jdk/java/awt/Dialog/ModalDialogTest/ModalDialogTest.java index 610b122e7f9..33fd97dfa6d 100644 --- a/test/jdk/java/awt/Dialog/ModalDialogTest/ModalDialogTest.java +++ b/test/jdk/java/awt/Dialog/ModalDialogTest/ModalDialogTest.java @@ -211,7 +211,7 @@ public void focusLost(FocusEvent e) { win.add(center, BorderLayout.CENTER); win.add(bottom, BorderLayout.SOUTH); win.pack(); - if (windows != 0) { + if (windows != 0 || frames != 1 || dialogs != 0 || modalDialogs != 0) { win.setVisible(true); } diff --git a/test/jdk/java/awt/FontClass/FontScalerRoundTest.java b/test/jdk/java/awt/FontClass/FontScalerRoundTest.java new file mode 100644 index 00000000000..49901683522 --- /dev/null +++ b/test/jdk/java/awt/FontClass/FontScalerRoundTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 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 8299255 + * @summary Verify no round error in Font scaling + */ + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; + +public class FontScalerRoundTest { + public static void main(String[] args) { + final double SCALE = 4096.0; + final double STEP = 0.0001; + final double LIMIT = STEP * 100.0; + + BufferedImage img = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = img.createGraphics(); + FontRenderContext frc = g2d.getFontRenderContext(); + + Font font = new Font(Font.DIALOG, Font.PLAIN, 1); + float h1 = getScaledHeight(font, frc, SCALE); + float h2 = getScaledHeight(font, frc, SCALE + STEP); + float diff = Math.abs(h1 - h2); + + if (diff > LIMIT) { + throw new RuntimeException("Font metrix had round error " + + h1 + "," + h2); + } + } + + private static float getScaledHeight(Font font, + FontRenderContext frc, + double scale) { + AffineTransform at = new AffineTransform(scale, 0.0, 0.0, scale, + 0.0, 0.0); + Font transFont = font.deriveFont(at); + LineMetrics m = transFont.getLineMetrics("0", frc); + return m.getHeight(); + } +} + diff --git a/test/jdk/java/awt/Frame/Iconify/IconifyTest.java b/test/jdk/java/awt/Frame/Iconify/IconifyTest.java new file mode 100644 index 00000000000..e2f2e316877 --- /dev/null +++ b/test/jdk/java/awt/Frame/Iconify/IconifyTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 1999, 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. + */ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicReference; +import javax.swing.SwingUtilities; + +/* + * @test + * @key headful + * @bug 8296934 + * @summary Verifies whether Undecorated Frame can be iconified or not. + * @run main IconifyTest + */ +public class IconifyTest { + + private static Robot robot; + private static Button button; + private static Frame frame; + private static volatile int windowStatusEventType; + private static volatile int windowIconifiedEventType; + private static volatile boolean focusGained = false; + + public static void initializeGUI() { + frame = new Frame(); + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + frame.setUndecorated(true); + + frame.addWindowFocusListener(new WindowAdapter() { + public void windowGainedFocus(WindowEvent event) { + focusGained = true; + } + }); + + frame.addWindowListener(new WindowAdapter() { + public void windowActivated(WindowEvent e) { + windowStatusEventType = WindowEvent.WINDOW_ACTIVATED; + System.out.println("Event encountered: " + e); + } + + public void windowIconified(WindowEvent e) { + windowIconifiedEventType = WindowEvent.WINDOW_ICONIFIED; + System.out.println("Event encountered: " + e); + } + + public void windowDeiconified(WindowEvent e) { + windowIconifiedEventType = WindowEvent.WINDOW_DEICONIFIED; + System.out.println("Event encountered: " + e); + } + + public void windowDeactivated(WindowEvent e) { + windowStatusEventType = WindowEvent.WINDOW_DEACTIVATED; + System.out.println("Event encountered: " + e); + } + }); + + button = new Button("Minimize me"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.setExtendedState(Frame.ICONIFIED); + } + }); + + frame.setBackground(Color.green); + frame.add(button); + frame.setLocationRelativeTo(null); + frame.toFront(); + frame.setVisible(true); + } + + public static void main(String[] args) throws AWTException, + InvocationTargetException, InterruptedException { + robot = new Robot(); + try { + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(IconifyTest::initializeGUI); + final AtomicReference frameloc = new AtomicReference<>(); + final AtomicReference framesize = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + frameloc.set(frame.getLocationOnScreen()); + framesize.set(frame.getSize()); + }); + Point locOnScreen = frameloc.get(); + Dimension frameSizeOnScreen = framesize.get(); + + robot.mouseMove(locOnScreen.x + frameSizeOnScreen.width / 2, + locOnScreen.y + frameSizeOnScreen.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + if (windowStatusEventType != WindowEvent.WINDOW_ACTIVATED) { + throw new RuntimeException( + "FAIL: WINDOW_ACTIVATED event did not occur when the undecorated frame is activated!"); + } + clearEventTypeValue(); + final AtomicReference buttonloc = new AtomicReference<>(); + final AtomicReference buttonsize = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + buttonloc.set(button.getLocationOnScreen()); + buttonsize.set(button.getSize()); + }); + Point buttonLocOnScreen = buttonloc.get(); + Dimension buttonSizeOnScreen = buttonsize.get(); + + robot.mouseMove(buttonLocOnScreen.x + buttonSizeOnScreen.width / 2, + buttonLocOnScreen.y + buttonSizeOnScreen.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (windowIconifiedEventType != WindowEvent.WINDOW_ICONIFIED) { + throw new RuntimeException( + "FAIL: WINDOW_ICONIFIED event did not occur when the undecorated frame is iconified!"); + } + if (windowStatusEventType != WindowEvent.WINDOW_DEACTIVATED) { + throw new RuntimeException( + "FAIL: WINDOW_DEACTIVATED event did not occur when the undecorated frame is iconified!"); + } + final AtomicReference frameHasFocus = new AtomicReference<>(); + SwingUtilities + .invokeAndWait(() -> frameHasFocus.set(frame.hasFocus())); + final boolean hasFocus = frameHasFocus.get(); + if (hasFocus) { + throw new RuntimeException( + "FAIL: The undecorated frame has focus even when it is iconified!"); + } + + clearEventTypeValue(); + + SwingUtilities + .invokeAndWait(() -> frame.setExtendedState(Frame.NORMAL)); + robot.waitForIdle(); + + if (windowIconifiedEventType != WindowEvent.WINDOW_DEICONIFIED) { + throw new RuntimeException( + "FAIL: WINDOW_DEICONIFIED event did not occur when the state is set to NORMAL!"); + } + if (windowStatusEventType != WindowEvent.WINDOW_ACTIVATED) { + throw new RuntimeException( + "FAIL: WINDOW_ACTIVATED event did not occur when the state is set to NORMAL!"); + } + if (!focusGained) { + throw new RuntimeException( + "FAIL: The undecorated frame does not have focus when it is deiconified!"); + } + System.out.println("Test passed"); + } + finally { + SwingUtilities.invokeAndWait(IconifyTest::disposeFrame); + } + } + + public static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + public static void clearEventTypeValue() { + windowIconifiedEventType = -1; + windowStatusEventType = -1; + focusGained = false; + } +} + diff --git a/test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java b/test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java index 50440917915..55baf940f87 100644 --- a/test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java +++ b/test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java @@ -25,7 +25,7 @@ /** * @test * @key headful - * @bug 8287600 8291266 + * @bug 8287600 8291266 8299207 * @requires os.family == "mac" * @summary [macosx] Some primitives do not render in metal pipeline * @run main DrawPrimitivesTest diff --git a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java index 4067bcea32e..4f789668c4a 100644 --- a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java +++ b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java @@ -34,11 +34,23 @@ * @run main DragWindowTest */ -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -import java.util.concurrent.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import java.util.concurrent.Callable; import test.java.awt.regtesthelpers.Util; @@ -55,7 +67,7 @@ public class DragWindowTest { public static void main(String[] args) throws Exception { Robot robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); SwingUtilities.invokeAndWait(new Runnable() { @@ -65,6 +77,7 @@ public void run() { } }); + robot.delay(250); robot.waitForIdle(); Point pointToClick = Util.invokeOnEDT(new Callable() { @@ -134,6 +147,7 @@ private static void createAndShowGUI() { panel.add(button, BorderLayout.CENTER); frame.getContentPane().add(panel); + frame.setLocationRelativeTo(null); frame.setVisible(true); } diff --git a/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java b/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java index 425588d6693..684ac9e2538 100644 --- a/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java +++ b/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java @@ -24,7 +24,7 @@ * @test * @bug 6614214 8198613 * @summary Verifies that we enter the fs mode on the correct screen. - * Here is how to test: start the test on on a multi-screen system. + * Here is how to test: start the test on a multi-screen system. * Verify that the display is correctly tracked by dragging the frame back * and forth between screens. Then verify that the correct device enters * the full-screen mode - when "Enter FS mode" is pressed it should enter on diff --git a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java index 55d9b4358af..8025bc9839e 100644 --- a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java +++ b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java @@ -40,7 +40,7 @@ /** * @test * @key headful - * @bug 8215105 8211999 + * @bug 8215105 8211999 8298887 * @summary tests that Robot can capture the common colors without artifacts * @run main/othervm CheckCommonColors * @run main/othervm -Xcheck:jni CheckCommonColors diff --git a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java index aa69f8fa4b7..784dc0ff18b 100644 --- a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java +++ b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -30,6 +30,7 @@ * @test * @key headful * @bug 4758438 + * @requires os.family == "linux" * @summary Testcase to check the implementation of RFE 4758438 * The RFE suggests that the GNOME desktop properties * should be made accessible through the @@ -43,12 +44,14 @@ public class rfe4758438 implements PropertyChangeListener { enum PROPS { drag_threshold( + "org.gnome.desktop.peripherals.mouse drag-threshold", "org.gnome.settings-daemon.peripherals.mouse drag-threshold", "/desktop/gnome/peripherals/mouse/drag_threshold", "gnome.Net/DndDragThreshold", "int", new String[]{"5", "6"}), double_click( + "org.gnome.desktop.peripherals.mouse double-click", "org.gnome.settings-daemon.peripherals.mouse double-click", "/desktop/gnome/peripherals/mouse/double_click", "gnome.Net/DoubleClickTime", @@ -56,31 +59,43 @@ enum PROPS { new String[]{"200","300"}), cursor_blink( "org.gnome.desktop.interface cursor-blink", + null, "/desktop/gnome/interface/cursor_blink", "gnome.Net/CursorBlink", "bool", new String[]{"true","false"}), cursor_blink_time( "org.gnome.desktop.interface cursor-blink-time", + null, "/desktop/gnome/interface/cursor_blink_time", "gnome.Net/CursorBlinkTime", "int", new String[]{"1000","1500"}), gtk_theme( "org.gnome.desktop.interface gtk-theme", + null, "/desktop/gnome/interface/gtk_theme", "gnome.Net/ThemeName", "string", new String[]{"Crux","Simple"}); public final String gsettings; + public final String gsettingsFallback; public final String gconftool; public final String java; public final String type; public final String[] values; - PROPS(String gsettings, String gconftool, String java, String type, String[] values){ + PROPS( + String gsettings, + String gsettingsFallback, + String gconftool, + String java, + String type, + String[] values + ){ this.gsettings = gsettings; + this.gsettingsFallback = gsettingsFallback; this.gconftool = gconftool; this.java = java; this.type = type; @@ -90,10 +105,10 @@ enum PROPS { static boolean useGsettings; static String tool; - Toolkit toolkit = Toolkit.getDefaultToolkit(); + final Toolkit toolkit = Toolkit.getDefaultToolkit(); String changedProperty; Object changedValue; - Object lock = new Object(); + final Object lock = new Object(); /** * Implementation of PropertyChangeListener method @@ -105,7 +120,7 @@ public void propertyChange(PropertyChangeEvent event) { synchronized(lock) { try { lock.notifyAll(); - } catch (Exception e) { + } catch (Exception ignored) { } } } @@ -132,6 +147,34 @@ void doTest() throws Exception { System.out.println("Test passed"); } + String prepareCommand(PROPS property, boolean useMain) { + //Create the command to execute + StringBuffer sb = new StringBuffer(tool); + if (useGsettings) { + sb.append(" set "); + sb.append( useMain + ? property.gsettings + : property.gsettingsFallback + ); + sb.append(" "); + } else { + sb.append(" --set --type="); + sb.append(property.type); + sb.append(" "); + sb.append(property.gconftool); + sb.append(" "); + } + return sb.toString(); + } + + int doTestCommand(String cmd) throws Exception { + //Initialize the variables and execute the command + changedProperty = ""; + changedValue = null; + + return executeCommand(cmd); + } + /** * Do the test for each property. Find the current value * of the property, set the property to a value not equal @@ -146,10 +189,10 @@ void doTest(PROPS property) throws Exception { //For boolean type values, getDesktopProperty method returns Integer objects if (property.type.equals("bool")) { - if (obj.equals(new Integer(1))) { - obj = new String("true"); + if (obj.equals(1)) { + obj = "true"; } else { - obj = new String("false"); + obj = "false"; } } Object value = property.values[0]; @@ -157,56 +200,53 @@ void doTest(PROPS property) throws Exception { value = property.values[1]; } - //Create the command to execute - StringBuffer sb = new StringBuffer(tool); - if (useGsettings) { - sb.append(" set "); - sb.append(property.gsettings); - sb.append(" "); - } else { - sb.append(" --set --type="); - sb.append(property.type); - sb.append(" "); - sb.append(property.gconftool); - sb.append(" "); - } - String tempCommand = sb.toString(); - sb.append(value.toString()); + String tempCommand = prepareCommand(property, true); - //Initialize the variables and execute the command - changedProperty = ""; - changedValue = null; - if (executeCommand(sb.toString()) != 0) - throw new RuntimeException("Could not execute the command"); + int retVal = doTestCommand(tempCommand + value); + + if (retVal != 0) { + if (useGsettings && property.gsettingsFallback != null) { + System.out.printf("Failed:\n\t%s\nTrying fallback:\n\t", tempCommand); + tempCommand = prepareCommand(property, false); + System.out.println(tempCommand); + + retVal = doTestCommand(tempCommand + value); + } + + if (retVal != 0) { + throw new RuntimeException("Could not execute the command"); + } + } synchronized(lock) { try { lock.wait(5000); - } catch (Exception e) { + } catch (Exception ignored) { } } + if (property.type.equals("bool")) { - if (changedValue.equals(new Integer(1))) { - changedValue = new String("true"); + if (changedValue.equals(1)) { + changedValue = "true"; } else { - changedValue = new String("false"); + changedValue = "false"; } } //Check if the event got triggered if (!changedProperty.equals(property.java)) { //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); throw new RuntimeException("PropertyChangedEvent did not occur for " + property.java); } else if (!changedValue.toString().equals(value.toString())) { //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); throw new RuntimeException("New value of the property is different from " + "the value supplied"); } //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); } /** @@ -231,9 +271,9 @@ int executeCommand(String command) throws Exception { stderr.append((char) es.read()); if (stdout.length() > 0) - System.out.println(stdout.toString()); + System.out.println(stdout); if (stderr.length() > 0) - System.err.println(stderr.toString()); + System.err.println(stderr); return process.exitValue(); } } diff --git a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh index 6a55d727c7b..ce5628ac9d4 100644 --- a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh +++ b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -28,18 +28,20 @@ OS=`uname` case "$OS" in Linux* ) - GNOMESID=`pgrep gnome-session` + GNOMESID=`pgrep gnome-session | head -n1` + + printf "\n/* gnome-session environ\n" + cat "/proc/$GNOMESID/environ" | tr '\0' '\n' + printf "\n*/\n\n" + DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$GNOMESID/environ | cut -d= -f2-` export DBUS_SESSION_BUS_ADDRESS + DISPLAY=`grep -z DISPLAY /proc/$GNOMESID/environ | cut -d= -f2-` export DISPLAY - ;; - Sun* ) - GNOMESID=`pgrep gnome-session` - DBUS_SESSION_BUS_ADDRESS=`pargs -e $GNOMESID | grep DBUS_SESSION_BUS_ADDRESS | cut -d= -f2-` - export DBUS_SESSION_BUS_ADDRESS - DISPLAY=`pargs -e $GNOMESID | grep DISPLAY | cut -d= -f2-` - export DISPLAY + + XDG_CURRENT_DESKTOP=`grep -z XDG_CURRENT_DESKTOP /proc/$GNOMESID/environ | cut -d= -f2-` + export XDG_CURRENT_DESKTOP ;; * ) echo "This Feature is not to be tested on $OS" @@ -47,13 +49,18 @@ case "$OS" in ;; esac -if [ ${GNOME_DESKTOP_SESSION_ID:-nonset} = "nonset" ]; +printf "\n/* Test env:\n\n" +env +printf "\n*/\n\n" + +XDG_GNOME=$(echo $XDG_CURRENT_DESKTOP | grep -i gnome) + +if [ -z "$XDG_GNOME" ] \ + && [ ${GNOME_DESKTOP_SESSION_ID:-nonset} = "nonset" ] \ + && [ ${GNOME_SESSION_NAME:-nonset} = "nonset" ] then - if [ ${GNOME_SESSION_NAME:-nonset} = "nonset" ]; - then - echo "This test should run under Gnome" - exit 0 - fi + echo "This test should run under Gnome" + exit 0 fi SCHEMAS=`gsettings list-schemas | wc -l` @@ -70,7 +77,11 @@ fi cd ${TESTSRC} echo $PWD echo "${TESTJAVA}/bin/javac -d ${TESTCLASSES} rfe4758438.java" + +set -e ${TESTJAVA}/bin/javac -d ${TESTCLASSES} rfe4758438.java +set +e + cd ${TESTCLASSES} ${TESTJAVA}/bin/java -DuseGsettings=${USE_GSETTINGS} -Dtool=${TOOL} ${TESTVMOPTS} rfe4758438 diff --git a/test/jdk/java/awt/a11y/AccessibleActionsTest.java b/test/jdk/java/awt/a11y/AccessibleActionsTest.java index 8a916d5527f..3f3f191a099 100644 --- a/test/jdk/java/awt/a11y/AccessibleActionsTest.java +++ b/test/jdk/java/awt/a11y/AccessibleActionsTest.java @@ -57,7 +57,7 @@ void createTest() { + "Check a11y actions.\n\n" + "Turn screen reader on, and Tab to the label.\n\n" + "Perform the VO action \"Press\" (VO+space)\n" - + "Perform the VO action \"Show menu\" (VO+Shift+m)\n\n" + + "Perform the VO action \"Show menu\" (Shift+VO+m)\n\n" + "If after the first action the text of the label has changed, and after the second action the menu appears tab further and press PASS, otherwise press FAIL."; exceptionString = "AccessibleAction test failed!"; @@ -67,7 +67,7 @@ void createTest() { void createTree() { INSTRUCTIONS = "INSTRUCTIONS:\n" + "Check a11y actions.\n\n" - + "Turn screen reader on, and Tab to the label.\n\n" + + "Turn screen reader on, and Tab to the tree.\n\n" + "Perform the VO action \"Press\" (VO+space) on tree nodes\n\n" + "If after press the tree node is expanded tab further and press PASS, otherwise press FAIL."; diff --git a/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java b/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java index f03af5d3a09..28da76bc17c 100644 --- a/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java +++ b/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java @@ -52,7 +52,7 @@ void createTabPane() { INSTRUCTIONS = "INSTRUCTIONS:\n" + "Check a11y of JTabbedPane.\n\n" + "Turn screen reader on, and tab to the JTabbedPane.\n" - + "Use page up and page down arrow buttons to move through the tabs.\n\n" + + "Use the left and right arrow buttons to move through the tabs.\n\n" + "If you can hear selected tab names tab further and press PASS, otherwise press FAIL.\n"; JTabbedPane tabbedPane = new JTabbedPane(); diff --git a/test/jdk/java/awt/a11y/AccessibleTextTest.java b/test/jdk/java/awt/a11y/AccessibleTextTest.java index 542d7bde082..0acb14ff694 100644 --- a/test/jdk/java/awt/a11y/AccessibleTextTest.java +++ b/test/jdk/java/awt/a11y/AccessibleTextTest.java @@ -58,8 +58,8 @@ private void createSimpleLabel() { + "Check a11y of JLabel.\n\n" + "Turn screen reader on.\n" + "On MacOS, use the VO navigation keys to read the label text;\n" - + "ON Windows with JAWS, use window virtualization (insert+alt+w and arrows) to read the label text;\n" - + "ON Windows with NVDA, use the browse cursor (insert+num4 or insert+num6) to read the label text;\n\n" + + "On Windows with JAWS, use JAWS cursor (num_minus and arrows) to read the label text;\n" + + "On Windows with NVDA, use the object navigation (insert+num4 or insert+num6) to read the label text;\n\n" + "If you can hear text from label tab further and press PASS, otherwise press FAIL."; JLabel label = new JLabel("this is a label"); diff --git a/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java b/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java index 015d46f03b2..bd1ea752edb 100644 --- a/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java +++ b/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java @@ -121,7 +121,7 @@ public void init() { "6) The output should contain data in three different formats", " provided by the system clipboard", " - Data after the \"ALL:\" marker should include the data", - " from the the \"SELECTION:\" marker", + " from the \"SELECTION:\" marker", " - Data after the \"FRAGMENT\" marker should include the data", " from the \"SELECTION:\" marker and may be some closing", " tags could be added to the mark-up", diff --git a/test/jdk/java/awt/event/ComponentEvent/ComponentItemEventTest.java b/test/jdk/java/awt/event/ComponentEvent/ComponentItemEventTest.java new file mode 100644 index 00000000000..4300cfa9357 --- /dev/null +++ b/test/jdk/java/awt/event/ComponentEvent/ComponentItemEventTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +/* + * @test + * @key headful + * @bug 8299296 + * @summary Verify that Component selection via mouse generates ItemEvent. + * @run main ComponentItemEventTest + */ +public class ComponentItemEventTest { + + private static Frame frame; + private volatile static Choice choice; + private volatile static Checkbox cb; + private static Robot robot; + private volatile static boolean cbStateChanged = false; + private volatile static boolean choiceStateChanged = false; + private volatile static Point compAt; + private volatile static Dimension compSize; + + private static void initializeGUI() { + frame = new Frame("Test Frame"); + frame.setLayout(new FlowLayout()); + choice = new Choice(); + for (int i = 0; i < 8; i++) { + choice.add("Choice "+i); + } + choice.select(3); + choice.addItemListener((event) -> { + System.out.println("Choice got an ItemEvent: " + event); + choiceStateChanged = true; + }); + + cb = new Checkbox("CB"); + cb.addItemListener((event) -> { + System.out.println("Checkbox got an ItemEvent: " + event); + cbStateChanged = true; + }); + frame.add(choice); + frame.add(cb); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ComponentItemEventTest::initializeGUI); + robot = new Robot(); + robot.setAutoDelay(1000); + robot.setAutoWaitForIdle(true); + + robot.waitForIdle(); + EventQueue.invokeAndWait(() -> { + compAt = choice.getLocationOnScreen(); + compSize = choice.getSize(); + }); + robot.mouseMove(compAt.x + choice.getSize().width - 10, + compAt.y + compSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(compAt.x + compSize.width / 2, + compAt.y + compSize.height + 15); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + if (!choiceStateChanged) { + throw new RuntimeException( + "FAIL: Choice did not trigger ItemEvent when item selected!"); + } + + EventQueue.invokeAndWait(() -> { + compAt = cb.getLocationOnScreen(); + compSize = cb.getSize(); + }); + robot.mouseMove(compAt.x + compSize.width / 2, + compAt.y + compSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + if (!cbStateChanged) { + throw new RuntimeException( + "FAIL: Checkbox did not trigger ItemEvent when item selected!"); + } + System.out.println("Test passed!"); + } finally { + EventQueue.invokeAndWait(ComponentItemEventTest::disposeFrame); + } + } + + public static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } +} diff --git a/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java b/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java deleted file mode 100644 index 1825244d0b0..00000000000 --- a/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2007, 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. - */ - -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.Point; -import java.awt.Robot; -import java.awt.TextArea; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -/* - * @test - * @key headful - * @bug 8296632 - * @summary Verify the content changes of a TextArea via TextListener. - * @run main TextAreaTextEventTest - */ -public class TextAreaTextEventTest { - - private static Frame frame; - private volatile static TextArea textArea; - private volatile static boolean textChanged = false; - private volatile static Point textAreaAt; - private volatile static Dimension textAreaSize; - private static Robot robot = null; - - public static void main(String[] args) throws Exception { - try { - EventQueue.invokeAndWait(TextAreaTextEventTest::initializeGUI); - - robot = new Robot(); - robot.setAutoDelay(100); - - robot.waitForIdle(); - EventQueue.invokeAndWait(() -> { - textAreaAt = textArea.getLocationOnScreen(); - textAreaSize = textArea.getSize(); - }); - robot.mouseMove(textAreaAt.x + textAreaSize.width / 2, - textAreaAt.y + textAreaSize.height / 2); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - typeKey(KeyEvent.VK_T); - - robot.waitForIdle(); - if (!textChanged) { - throw new RuntimeException( - "FAIL: TextEvent not triggered when key 'T' typed on TextArea"); - } - - typeKey(KeyEvent.VK_E); - typeKey(KeyEvent.VK_S); - typeKey(KeyEvent.VK_T); - - textChanged = false; - typeKey(KeyEvent.VK_ENTER); - - robot.waitForIdle(); - if (!textChanged) { - throw new RuntimeException( - "FAIL: TextEvent not triggered when Enter pressed on TextArea"); - } - - textChanged = false; - robot.mouseMove(textAreaAt.x + 4, textAreaAt.y + 10); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - for (int i = 0; i < textAreaSize.width / 2; i++) { - robot.mouseMove(textAreaAt.x + 4 + i, textAreaAt.y + 10); - } - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - - robot.waitForIdle(); - if (textChanged) { - throw new RuntimeException( - "FAIL: TextEvent triggered when text is selected on TextArea!"); - } - - textChanged = false; - typeKey(KeyEvent.VK_F3); - - robot.waitForIdle(); - if (textChanged) { - throw new RuntimeException( - "FAIL: TextEvent triggered when special key F3 is pressed on TextArea!"); - } - System.out.println("Test passed!"); - } finally { - EventQueue.invokeAndWait(TextAreaTextEventTest::disposeFrame); - } - } - - private static void initializeGUI() { - frame = new Frame("Test Frame"); - frame.setLayout(new FlowLayout()); - textArea = new TextArea(5, 15); - textArea.addTextListener((event) -> { - System.out.println("Got a text event: " + event); - textChanged = true; - }); - frame.add(textArea); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } - - public static void disposeFrame() { - if (frame != null) { - frame.dispose(); - } - } - - private static void typeKey(int key) throws Exception { - robot.keyPress(key); - robot.keyRelease(key); - } -} diff --git a/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java b/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java new file mode 100644 index 00000000000..8ffd151fde2 --- /dev/null +++ b/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2007, 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. + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +/* + * @test + * @key headful + * @bug 8297489 8296632 + * @summary Verify the content changes of a TextComponent via TextListener. + * @run main TextComponentTextEventTest + */ +public class TextComponentTextEventTest { + + private static Frame frame; + private static Robot robot = null; + private volatile static TextComponent[] components; + private volatile static boolean textChanged = false; + private volatile static Point textCompAt; + private volatile static Dimension textCompSize; + + private static void initializeGUI() { + TextField textField = new TextField(20); + textField.addTextListener((event) -> { + textChanged = true; + System.out.println("TextField got a text event: " + event); + }); + + TextArea textArea = new TextArea(5, 15); + textArea.addTextListener((event) -> { + System.out.println("TextArea got a text event: " + event); + textChanged = true; + }); + + components = new TextComponent[] { textField, textArea }; + + frame = new Frame("Test Frame"); + frame.setLayout(new FlowLayout()); + for (TextComponent textComp : components) { + frame.add(textComp); + } + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(TextComponentTextEventTest::initializeGUI); + robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + for (TextComponent textComp : components) { + robot.waitForIdle(); + EventQueue.invokeAndWait(() -> { + textCompAt = textComp.getLocationOnScreen(); + textCompSize = textComp.getSize(); + }); + + robot.mouseMove(textCompAt.x + textCompSize.width / 2, + textCompAt.y + textCompSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + typeKey(KeyEvent.VK_T); + + robot.waitForIdle(); + if (!textChanged) { + throw new RuntimeException( + "FAIL: TextEvent not triggered when text entered in " + textComp); + } + + typeKey(KeyEvent.VK_E); + typeKey(KeyEvent.VK_S); + typeKey(KeyEvent.VK_T); + + textChanged = false; + typeKey(KeyEvent.VK_ENTER); + + robot.waitForIdle(); + if (textComp instanceof TextField && textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when Enter pressed on " + textComp); + } else if (textComp instanceof TextArea && !textChanged) { + throw new RuntimeException( + "FAIL: TextEvent not triggered when Enter pressed on " + textComp); + } + + textChanged = false; + robot.mouseMove(textCompAt.x + 4, textCompAt.y + 10); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (int i = 0; i < textCompSize.width / 2; i++) { + robot.mouseMove(textCompAt.x + 4 + i, textCompAt.y + 10); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + if (textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when selection made in " + textComp); + } + + textChanged = false; + typeKey(KeyEvent.VK_F3); + + robot.waitForIdle(); + if (textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when F3 pressed on " + textComp); + } + } + System.out.println("Test passed!"); + } finally { + EventQueue.invokeAndWait(TextComponentTextEventTest::disposeFrame); + } + } + + public static void disposeFrame() { + if (frame != null) { + frame.dispose(); + } + } + + private static void typeKey(int key) { + robot.keyPress(key); + robot.keyRelease(key); + } +} diff --git a/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java b/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java index 65acd420345..986d4bcf5d3 100644 --- a/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java +++ b/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8240756 + * @bug 8240756 8298887 * @summary Non-English characters are printed with wrong glyphs on MacOS * @modules java.desktop/sun.java2d java.desktop/sun.java2d.loops java.desktop/sun.font * @requires os.family == "mac" diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java new file mode 100644 index 00000000000..532a1b8a106 --- /dev/null +++ b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 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 8165943 + * @summary LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set + * @library ../../regtesthelpers + * @build PassFailJFrame + * @run main/manual LineBreakWithTracking + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.text.AttributedString; +import java.util.Hashtable; +import java.lang.reflect.InvocationTargetException; + +class LineBreakPanel extends JPanel implements ActionListener { + + private float textTracking = 0.0f; + private static String fontName = "Dialog"; + private static String text = "This is a long line of text that should be broken across multiple lines. " + + "Please set the different tracking values to test via menu! This test should pass if " + + "these lines are broken to fit the width, and fail otherwise. It should " + + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " + + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " + + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" + + "\u67b8\u67b9) text correctly."; + + private LineBreakMeasurer lineMeasurer; + + public void actionPerformed(ActionEvent e) { + textTracking = (float)((JRadioButtonMenuItem)e.getSource()).getClientProperty( "tracking" ); + lineMeasurer = null; + invalidate(); + repaint(); + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + setBackground(Color.white); + + Graphics2D g2d = (Graphics2D)g; + + if (lineMeasurer == null) { + Float regular = Float.valueOf(16.0f); + Float big = Float.valueOf(24.0f); + + Hashtable map = new Hashtable(); + map.put(TextAttribute.SIZE, (float)18.0); + map.put(TextAttribute.TRACKING, (float)textTracking); + + AttributedString astr = new AttributedString(text, map); + astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); + astr.addAttribute(TextAttribute.FAMILY, fontName, 0, text.length()); + + int ix = text.indexOf("broken"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("hebrew"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("arabic"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("CJK"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); + + FontRenderContext frc = g2d.getFontRenderContext(); + lineMeasurer = new LineBreakMeasurer(astr.getIterator(), frc); + } + + lineMeasurer.setPosition(0); + + float w = (float)getSize().width; + float x = 0, y = 0; + TextLayout layout; + while ((layout = lineMeasurer.nextLayout(w)) != null) { + x = layout.isLeftToRight() ? 0 : w - layout.getAdvance(); + y += layout.getAscent(); + layout.draw(g2d, x, y); + y += layout.getDescent() + layout.getLeading(); + } + } +} + +public class LineBreakWithTracking { + + private static final String INSTRUCTIONS = """ + This manual test verifies that LineBreakMeasurer measures the lines' + breaks correctly taking into account the TextAttribute.TRACKING value. + The test string includes Latin, Arabic, CJK and Hebrew. + + You should choose a tracking value from the menu and resize the window. + If the text lines break exactly to the wrapping width: + no room for one more word exists and + the text lines are not too long for given wrapping width, - + then press PASS, otherwise - FAIL. + """; + + public void createGUI(JFrame frame) { + + LineBreakPanel panel = new LineBreakPanel(); + frame.getContentPane().add(panel, BorderLayout.CENTER); + + JMenuBar menuBar = new JMenuBar(); + + JMenu menu = new JMenu("Tracking"); + ButtonGroup btnGroup = new ButtonGroup(); + String btnLabels[] = {"-0.1", "0", "0.1", "0.2", "0.3"}; + float val = -0.1f; + for (String label : btnLabels) { + JRadioButtonMenuItem btn = new JRadioButtonMenuItem(label); + btn.putClientProperty( "tracking", val ); + btn.addActionListener(panel); + btnGroup.add(btn); + menu.add(btn); + val += 0.1f; + } + menuBar.add(menu); + + frame.setJMenuBar(menuBar); + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + + JFrame frame = new JFrame("LineBreakMeasurer with Tracking"); + frame.setSize(new Dimension(640, 480)); + + LineBreakWithTracking controller = new LineBreakWithTracking(); + controller.createGUI(frame); + + PassFailJFrame passFailJFrame = new PassFailJFrame(INSTRUCTIONS); + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + frame.setVisible(true); + passFailJFrame.awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java new file mode 100644 index 00000000000..32b1f0592d9 --- /dev/null +++ b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 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 8165943 + @summary LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set + @run main/othervm LineBreakWithTrackingAuto +*/ + +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.text.AttributedString; + +public class LineBreakWithTrackingAuto { + + private static final String WORD = "word"; + private static final String SPACE = " "; + private static final int NUM_WORDS = 12; + private static final float FONT_SIZE = 24.0f; + private static final float TEXT_TRACKING[] = { -0.1f, 0f, 0.1f, 0.2f, 0.3f }; + private static final float EPSILON = 0.005f; + + + public static void main(String[] args) { + new LineBreakWithTrackingAuto().test(); + } + + public void test() { + + final FontRenderContext frc = new FontRenderContext(null, false, false); + + // construct a paragraph as follows: [SPACE + WORD] + ... + StringBuffer text = new StringBuffer(); + for (int i = 0; i < NUM_WORDS; i++) { + text.append(SPACE); + text.append(WORD); + } + AttributedString attrString = new AttributedString(text.toString()); + attrString.addAttribute(TextAttribute.SIZE, Float.valueOf(FONT_SIZE)); + + // test different tracking values: -0.1f, 0f, 0.1f, 0.2f, 0.3f + for (float textTracking : TEXT_TRACKING) { + + final float trackingAdvance = FONT_SIZE * textTracking; + attrString.addAttribute(TextAttribute.TRACKING, textTracking); + + LineBreakMeasurer measurer = new LineBreakMeasurer(attrString.getIterator(), frc); + + final int sequenceLength = WORD.length() + SPACE.length(); + final float sequenceAdvance = getSequenceAdvance(measurer, text.length(), sequenceLength); + final float textAdvance = NUM_WORDS * sequenceAdvance; + + // test different wrapping width starting from the WORD+SPACE to TEXT width + for (float wrappingWidth = sequenceAdvance; wrappingWidth < textAdvance; wrappingWidth += sequenceAdvance / sequenceLength) { + + measurer.setPosition(0); + + // break a paragraph into lines that fit the given wrapping width + do { + TextLayout layout = measurer.nextLayout(wrappingWidth); + float visAdvance = layout.getVisibleAdvance(); + + int currPos = measurer.getPosition(); + if ((trackingAdvance <= 0 && visAdvance - wrappingWidth > EPSILON) + || (trackingAdvance > 0 && visAdvance - wrappingWidth > trackingAdvance + EPSILON)) { + throw new Error("text line is too long for given wrapping width"); + } + + if (currPos < text.length() && visAdvance <= wrappingWidth - sequenceAdvance) { + throw new Error("text line is too short for given wrapping width"); + } + } while (measurer.getPosition() != text.length()); + + } + } + } + + private float getSequenceAdvance(LineBreakMeasurer measurer, int textLength, int sequenceLength) { + + measurer.setPosition(textLength - sequenceLength); + + TextLayout layout = measurer.nextLayout(10000.0f); + if (layout.getCharacterCount() != sequenceLength) { + throw new Error("layout length is incorrect"); + } + + return layout.getVisibleAdvance(); + } + +} diff --git a/test/jdk/java/awt/font/TextLayout/TestOldHangul.java b/test/jdk/java/awt/font/TextLayout/TestOldHangul.java index b52ba38557d..5327c20dba3 100644 --- a/test/jdk/java/awt/font/TextLayout/TestOldHangul.java +++ b/test/jdk/java/awt/font/TextLayout/TestOldHangul.java @@ -21,7 +21,7 @@ * */ -/* @test @(#)TestOldHangul.java +/* @test * @summary Verify Old Hangul display * @bug 6886358 * @ignore Requires a special font installed. @@ -80,4 +80,3 @@ public void actionPerformed(ActionEvent actionEvent) { frame.setVisible(true); } } - diff --git a/test/jdk/java/awt/font/TextLayout/TestTibetan.java b/test/jdk/java/awt/font/TextLayout/TestTibetan.java index bc55472a3cd..86594ddf4c1 100644 --- a/test/jdk/java/awt/font/TextLayout/TestTibetan.java +++ b/test/jdk/java/awt/font/TextLayout/TestTibetan.java @@ -21,7 +21,7 @@ * */ -/* @test @(#)TestTibetan.java +/* @test * @summary verify tibetan output * @bug 6886358 * @ignore Requires a special font installed @@ -84,4 +84,3 @@ public void actionPerformed(ActionEvent actionEvent) { frame.setVisible(true); } } - diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java b/test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java similarity index 51% rename from test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java rename to test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java index baa6b306b9a..e2274497256 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java +++ b/test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 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. * * This code is free software; you can redistribute it and/or modify it @@ -21,30 +21,34 @@ * questions. */ -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; +import java.awt.image.ColorModel; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersBuffering - extends FlowSubscriberBlackboxVerification> { +/** + * @test + * @bug 4677581 + * @summary checks when the ColorModel#getComponentSize() throws AIOBE + */ +public final class GetComponentSizeAIOBE { - public BodySubscribersBuffering() { - super(new TestEnvironment(450L)); - } + public static void main(String[] args) { + ColorModel cm = ColorModel.getRGBdefault(); + for (int i = 0; i < cm.getNumComponents(); ++i) { + cm.getComponentSize(i); + } - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.buffering(BodySubscribers.discarding(), - S.randomIntUpTo(1024) + 1); + testAIOBE(cm, Integer.MIN_VALUE); + testAIOBE(cm, -1); + testAIOBE(cm, cm.getNumComponents()); + testAIOBE(cm, cm.getNumComponents() + 1); + testAIOBE(cm, Integer.MAX_VALUE); } - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); + private static void testAIOBE(ColorModel cm, int componentIdx) { + try { + cm.getComponentSize(componentIdx); + throw new RuntimeException("AIOBE is not thrown"); + } catch (ArrayIndexOutOfBoundsException ignore) { + // expected + } } } diff --git a/test/jdk/java/awt/print/PrinterJob/ImagePrinting/PrintARGBImage.java b/test/jdk/java/awt/print/PrinterJob/ImagePrinting/PrintARGBImage.java index cba4e358c4c..4bef1cce0f5 100644 --- a/test/jdk/java/awt/print/PrinterJob/ImagePrinting/PrintARGBImage.java +++ b/test/jdk/java/awt/print/PrinterJob/ImagePrinting/PrintARGBImage.java @@ -54,6 +54,7 @@ public static void main(String[] args) throws InterruptedException, """; PassFailJFrame passFailJFrame = new PassFailJFrame(instruction, 10); + PassFailJFrame.positionTestWindow(null, PassFailJFrame.Position.HORIZONTAL); try { PrinterJob pj = PrinterJob.getPrinterJob(); pj.setPrintable(new PrintARGBImage()); diff --git a/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java b/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java index 7cb9a2bd3ff..2515e11e9ec 100644 --- a/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java +++ b/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java @@ -34,7 +34,7 @@ public class PageFormatChange { static String[] text = { - "This is is a manual test intended to be run on Windows, and you", + "This is a manual test intended to be run on Windows, and you", "must have at least two printers installed, and ideally the second", "printer should support large paper sizes. When the pageDialog appears", "first change printers, then choose a large paper size, then OK", diff --git a/test/jdk/java/awt/print/PrinterJob/PageRangesDlgTest.java b/test/jdk/java/awt/print/PrinterJob/PageRangesDlgTest.java index 4b1b860492a..cc5cfccc735 100644 --- a/test/jdk/java/awt/print/PrinterJob/PageRangesDlgTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PageRangesDlgTest.java @@ -81,6 +81,7 @@ public static void main(String[] args) throws Exception { """; PassFailJFrame passFailJFrame = new PassFailJFrame(instruction, 10); + PassFailJFrame.positionTestWindow(null, PassFailJFrame.Position.HORIZONTAL); showPrintDialogs(); passFailJFrame.awaitAndCheck(); } diff --git a/test/jdk/java/awt/regtesthelpers/Util.java b/test/jdk/java/awt/regtesthelpers/Util.java index d0ec8bcc5c9..8ea239b2036 100644 --- a/test/jdk/java/awt/regtesthelpers/Util.java +++ b/test/jdk/java/awt/regtesthelpers/Util.java @@ -450,6 +450,7 @@ public static int getWMID() { Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); // We may be called from non-X11 system, and this permission cannot be delegated to a test. m_addExports.invoke(null, "sun.awt.X11", Util.class.getModule()); + @SuppressWarnings("removal") Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { diff --git a/test/jdk/java/foreign/CallGeneratorHelper.java b/test/jdk/java/foreign/CallGeneratorHelper.java index f075616f582..e1ef460603b 100644 --- a/test/jdk/java/foreign/CallGeneratorHelper.java +++ b/test/jdk/java/foreign/CallGeneratorHelper.java @@ -22,17 +22,9 @@ * */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.ValueLayout; +import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; import java.util.ArrayList; @@ -387,21 +379,21 @@ static void generateUpcallFunction(String fName, Ret ret, List params @SuppressWarnings("unchecked") static Object makeArg(MemoryLayout layout, List> checks, boolean check) throws ReflectiveOperationException { if (layout instanceof GroupLayout) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); initStruct(segment, (GroupLayout)layout, checks, check); return segment; } else if (isPointer(layout)) { - MemorySegment segment = MemorySegment.allocateNative(1, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(1L, SegmentScope.auto()); if (check) { checks.add(o -> { try { - assertEquals(o, segment.address()); + assertEquals(o, segment); } catch (Throwable ex) { throw new IllegalStateException(ex); } }); } - return segment.address(); + return segment; } else if (layout instanceof ValueLayout) { if (isIntegral(layout)) { if (check) { @@ -426,7 +418,7 @@ static Object makeArg(MemoryLayout layout, List> checks, boolea static void initStruct(MemorySegment str, GroupLayout g, List> checks, boolean check) throws ReflectiveOperationException { for (MemoryLayout l : g.memberLayouts()) { - if (l.isPadding()) continue; + if (l instanceof PaddingLayout) continue; VarHandle accessor = g.varHandle(MemoryLayout.PathElement.groupElement(l.name().get())); List> fieldsCheck = new ArrayList<>(); Object value = makeArg(l, fieldsCheck, check); @@ -447,19 +439,17 @@ static void initStruct(MemorySegment str, GroupLayout g, List> } } - static Class carrier(MemoryLayout layout, boolean param) { + static Class carrier(MemoryLayout layout) { if (layout instanceof GroupLayout) { return MemorySegment.class; - } if (isPointer(layout)) { - return param ? Addressable.class : MemoryAddress.class; - } else if (layout instanceof ValueLayout valueLayout) { + } if (layout instanceof ValueLayout valueLayout) { return valueLayout.carrier(); } else { throw new IllegalStateException("Unexpected layout: " + layout); } } - MethodHandle downcallHandle(Linker abi, Addressable symbol, SegmentAllocator allocator, FunctionDescriptor descriptor) { + MethodHandle downcallHandle(Linker abi, MemorySegment symbol, SegmentAllocator allocator, FunctionDescriptor descriptor) { MethodHandle mh = abi.downcallHandle(symbol, descriptor); if (descriptor.returnLayout().isPresent() && descriptor.returnLayout().get() instanceof GroupLayout) { mh = mh.bindTo(allocator); diff --git a/test/jdk/java/foreign/LibraryLookupTest.java b/test/jdk/java/foreign/LibraryLookupTest.java index 9a7f321807e..b5108b5a63e 100644 --- a/test/jdk/java/foreign/LibraryLookupTest.java +++ b/test/jdk/java/foreign/LibraryLookupTest.java @@ -23,11 +23,11 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.nio.file.Path; @@ -51,12 +51,12 @@ public class LibraryLookupTest { @Test void testLoadLibraryConfined() { - try (MemorySession session0 = MemorySession.openConfined()) { - callFunc(loadLibrary(session0)); - try (MemorySession session1 = MemorySession.openConfined()) { - callFunc(loadLibrary(session1)); - try (MemorySession session2 = MemorySession.openConfined()) { - callFunc(loadLibrary(session2)); + try (Arena arena0 = Arena.openConfined()) { + callFunc(loadLibrary(arena0.scope())); + try (Arena arena1 = Arena.openConfined()) { + callFunc(loadLibrary(arena1.scope())); + try (Arena arena2 = Arena.openConfined()) { + callFunc(loadLibrary(arena2.scope())); } } } @@ -64,21 +64,21 @@ void testLoadLibraryConfined() { @Test(expectedExceptions = IllegalStateException.class) void testLoadLibraryConfinedClosed() { - Addressable addr; - try (MemorySession session = MemorySession.openConfined()) { - addr = loadLibrary(session); + MemorySegment addr; + try (Arena arena = Arena.openConfined()) { + addr = loadLibrary(arena.scope()); } callFunc(addr); } - private static Addressable loadLibrary(MemorySession session) { + private static MemorySegment loadLibrary(SegmentScope session) { SymbolLookup lib = SymbolLookup.libraryLookup(LIB_PATH, session); - MemorySegment addr = lib.lookup("inc").get(); - assertEquals(addr.session(), session); + MemorySegment addr = lib.find("inc").get(); + assertEquals(addr.scope(), session); return addr; } - private static void callFunc(Addressable addr) { + private static void callFunc(MemorySegment addr) { try { INC.invokeExact(addr); } catch (IllegalStateException ex) { @@ -94,12 +94,12 @@ private static void callFunc(Addressable addr) { @Test(expectedExceptions = IllegalArgumentException.class) void testBadLibraryLookupName() { - SymbolLookup.libraryLookup("nonExistent", MemorySession.global()); + SymbolLookup.libraryLookup("nonExistent", SegmentScope.global()); } @Test(expectedExceptions = IllegalArgumentException.class) void testBadLibraryLookupPath() { - SymbolLookup.libraryLookup(Path.of("nonExistent"), MemorySession.global()); + SymbolLookup.libraryLookup(Path.of("nonExistent"), SegmentScope.global()); } @Test @@ -116,8 +116,8 @@ static class LibraryLoadAndAccess implements Runnable { @Override public void run() { for (int i = 0 ; i < ITERATIONS ; i++) { - try (MemorySession session = MemorySession.openConfined()) { - callFunc(loadLibrary(session)); + try (Arena arena = Arena.openConfined()) { + callFunc(loadLibrary(arena.scope())); } } } @@ -125,15 +125,15 @@ public void run() { @Test void testLoadLibrarySharedClosed() throws Throwable { - MemorySession session = MemorySession.openShared(); - Addressable addr = loadLibrary(session); + Arena arena = Arena.openShared(); + MemorySegment addr = loadLibrary(arena.scope()); ExecutorService accessExecutor = Executors.newCachedThreadPool(); for (int i = 0; i < NUM_ACCESSORS ; i++) { accessExecutor.execute(new LibraryAccess(addr)); } while (true) { try { - session.close(); + arena.close(); break; } catch (IllegalStateException ex) { // wait for addressable parameter to be released @@ -146,9 +146,9 @@ void testLoadLibrarySharedClosed() throws Throwable { static class LibraryAccess implements Runnable { - final Addressable addr; + final MemorySegment addr; - LibraryAccess(Addressable addr) { + LibraryAccess(MemorySegment addr) { this.addr = addr; } diff --git a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java new file mode 100644 index 00000000000..205ce9c7083 --- /dev/null +++ b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020, 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 + * @enablePreview + * @run testng/othervm MemoryLayoutPrincipalTotalityTest + */ + +import org.testng.annotations.*; + +import java.lang.foreign.*; + +import static java.lang.foreign.ValueLayout.*; +import static org.testng.Assert.*; + +public class MemoryLayoutPrincipalTotalityTest { + + // The tests in this class is mostly there to ensure compile-time pattern matching totality. + + @Test + public void testBasicTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + int v0 = switch (memoryLayout) { + case MemoryLayout ml -> 1; + }; + assertEquals(v0, 1); + } + + @Test + public void testMLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v1 = switch (memoryLayout) { + case GroupLayout gl -> 0; + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case ValueLayout vl -> 1; + }; + assertEquals(v1, 1); + } + + @Test + public void testMLGLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v2 = switch (memoryLayout) { + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case ValueLayout vl -> 1; + case StructLayout sl -> 0; // leaf + case UnionLayout ul -> 0; // leaf + }; + assertEquals(v2, 1); + } + + @Test + public void testMLGLVLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v3 = switch (memoryLayout) { + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case StructLayout sl -> 0; // leaf + case UnionLayout ul -> 0; // leaf + case OfAddress oa -> 0; // leaf + case OfBoolean ob -> 0; // leaf + case OfByte ob -> 0; // leaf + case OfChar oc -> 0; // leaf + case OfDouble od -> 0; // leaf + case OfFloat of -> 0; // leaf + case OfInt oi -> 1; // leaf + case OfLong ol -> 0; // leaf + case OfShort os -> 0; // leaf + }; + assertEquals(v3, 1); + } + + @Test + public void testMLVLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v4 = switch (memoryLayout) { + case GroupLayout gl -> 0; + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case OfAddress oa -> 0; // leaf + case OfBoolean ob -> 0; // leaf + case OfByte ob -> 0; // leaf + case OfChar oc -> 0; // leaf + case OfDouble od -> 0; // leaf + case OfFloat of -> 0; // leaf + case OfInt oi -> 1; // leaf + case OfLong ol -> 0; // leaf + case OfShort os -> 0; // leaf + }; + assertEquals(v4, 1); + } + + private static MemoryLayout javaIntMemoryLayout() { + return JAVA_INT; + } + +} diff --git a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java new file mode 100644 index 00000000000..31a38813330 --- /dev/null +++ b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2020, 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 + * @enablePreview + * @run testng/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.*; + +public class MemoryLayoutTypeRetentionTest { + + // These tests check both compile-time and runtime properties. + // withName() et al. should return the same type as the original object. + + private static final String NAME = "a"; + private static final long BIT_ALIGNMENT = 64; + private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN; + + @Test + public void testOfBoolean() { + OfBoolean v = JAVA_BOOLEAN + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfByte() { + OfByte v = JAVA_BYTE + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfShort() { + OfShort v = JAVA_SHORT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfInt() { + OfInt v = JAVA_INT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfChar() { + OfChar v = JAVA_CHAR + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfLong() { + OfLong v = JAVA_LONG + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfFloat() { + OfFloat v = JAVA_FLOAT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfDouble() { + OfDouble v = JAVA_DOUBLE + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfAddress() { + OfAddress v = ADDRESS + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + assertFalse(v.isUnbounded()); + OfAddress v2 = v.asUnbounded(); + assertTrue(v2.isUnbounded()); + } + + @Test + public void testPaddingLayout() { + PaddingLayout v = MemoryLayout.paddingLayout(8) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testGroupLayout() { + GroupLayout v = MemoryLayout.structLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testStructLayout() { + StructLayout v = MemoryLayout.structLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testUnionLayout() { + UnionLayout v = MemoryLayout.unionLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + public void check(ValueLayout v) { + check((MemoryLayout) v); + assertEquals(v.order(), BYTE_ORDER); + } + + public void check(MemoryLayout v) { + assertEquals(v.name().orElseThrow(), NAME); + assertEquals(v.bitAlignment(), BIT_ALIGNMENT); + assertEquals(v.byteSize() * 8, v.bitSize()); + } + +} diff --git a/test/jdk/java/foreign/NativeTestHelper.java b/test/jdk/java/foreign/NativeTestHelper.java index e4fa9cc6be3..2d48f2e386c 100644 --- a/test/jdk/java/foreign/NativeTestHelper.java +++ b/test/jdk/java/foreign/NativeTestHelper.java @@ -22,18 +22,21 @@ * */ -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; public class NativeTestHelper { + public static final boolean IS_WINDOWS = System.getProperty("os.name").startsWith("Windows"); + public static boolean isIntegral(MemoryLayout layout) { return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier()); } @@ -44,7 +47,7 @@ static boolean isIntegral(Class clazz) { } public static boolean isPointer(MemoryLayout layout) { - return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemoryAddress.class; + return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class; } // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms. @@ -81,17 +84,17 @@ public static boolean isPointer(MemoryLayout layout) { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64).asUnbounded(); - private static Linker LINKER = Linker.nativeLinker(); + private static final Linker LINKER = Linker.nativeLinker(); private static final MethodHandle FREE = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); + LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER)); private static final MethodHandle MALLOC = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(C_POINTER, C_LONG_LONG)); - public static void freeMemory(Addressable address) { + public static void freeMemory(MemorySegment address) { try { FREE.invokeExact(address); } catch (Throwable ex) { @@ -99,15 +102,28 @@ public static void freeMemory(Addressable address) { } } - public static MemoryAddress allocateMemory(long size) { + public static MemorySegment allocateMemory(long size) { try { - return (MemoryAddress)MALLOC.invokeExact(size); + return (MemorySegment) MALLOC.invokeExact(size); } catch (Throwable ex) { throw new IllegalStateException(ex); } } - public static Addressable findNativeOrThrow(String name) { - return SymbolLookup.loaderLookup().lookup(name).orElseThrow(); + public static MemorySegment findNativeOrThrow(String name) { + return SymbolLookup.loaderLookup().find(name).orElseThrow(); + } + + public static MethodHandle downcallHandle(String symbol, FunctionDescriptor desc, Linker.Option... options) { + return LINKER.downcallHandle(findNativeOrThrow(symbol), desc, options); + } + + public static MemorySegment upcallStub(Class holder, String name, FunctionDescriptor descriptor) { + try { + MethodHandle target = MethodHandles.lookup().findStatic(holder, name, descriptor.toMethodType()); + return LINKER.upcallStub(target, descriptor, SegmentScope.auto()); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } } } diff --git a/test/jdk/java/foreign/SafeFunctionAccessTest.java b/test/jdk/java/foreign/SafeFunctionAccessTest.java index f638814c4f9..5873afb2308 100644 --- a/test/jdk/java/foreign/SafeFunctionAccessTest.java +++ b/test/jdk/java/foreign/SafeFunctionAccessTest.java @@ -28,18 +28,20 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED SafeFunctionAccessTest */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.foreign.VaList; +import java.util.stream.Stream; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -56,10 +58,10 @@ public class SafeFunctionAccessTest extends NativeTestHelper { @Test(expectedExceptions = IllegalStateException.class) public void testClosedStruct() throws Throwable { MemorySegment segment; - try (MemorySession session = MemorySession.openConfined()) { - segment = MemorySegment.allocateNative(POINT, session); + try (Arena arena = Arena.openConfined()) { + segment = arena.allocate(POINT); } - assertFalse(segment.session().isAlive()); + assertFalse(segment.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("struct_func"), FunctionDescriptor.ofVoid(POINT)); @@ -72,33 +74,39 @@ public void testClosedStructAddr_6() throws Throwable { MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func_6"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER)); + record Allocation(Arena drop, MemorySegment segment) { + static Allocation of(MemoryLayout layout) { + Arena arena = Arena.openShared(); + return new Allocation(arena, arena.allocate(layout)); + } + } for (int i = 0 ; i < 6 ; i++) { - MemorySegment[] segments = new MemorySegment[]{ - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()) + Allocation[] allocations = new Allocation[]{ + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT) }; // check liveness - segments[i].session().close(); + allocations[i].drop().close(); for (int j = 0 ; j < 6 ; j++) { if (i == j) { - assertFalse(segments[j].session().isAlive()); + assertFalse(allocations[j].drop().scope().isAlive()); } else { - assertTrue(segments[j].session().isAlive()); + assertTrue(allocations[j].drop().scope().isAlive()); } } try { - handle.invokeWithArguments(segments); + handle.invokeWithArguments(Stream.of(allocations).map(Allocation::segment).toArray()); fail(); } catch (IllegalStateException ex) { assertTrue(ex.getMessage().contains("Already closed")); } for (int j = 0 ; j < 6 ; j++) { if (i != j) { - segments[j].session().close(); // should succeed! + allocations[j].drop().close(); // should succeed! } } } @@ -107,30 +115,30 @@ public void testClosedStructAddr_6() throws Throwable { @Test(expectedExceptions = IllegalStateException.class) public void testClosedVaList() throws Throwable { VaList list; - try (MemorySession session = MemorySession.openConfined()) { - list = VaList.make(b -> b.addVarg(C_INT, 42), session); + try (Arena arena = Arena.openConfined()) { + list = VaList.make(b -> b.addVarg(C_INT, 42), arena.scope()); } - assertFalse(list.session().isAlive()); + assertFalse(list.segment().scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func"), FunctionDescriptor.ofVoid(C_POINTER)); - handle.invokeExact((Addressable)list); + handle.invokeExact(list.segment()); } @Test(expectedExceptions = IllegalStateException.class) public void testClosedUpcall() throws Throwable { MemorySegment upcall; - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); - upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), session); + upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), arena.scope()); } - assertFalse(upcall.session().isAlive()); + assertFalse(upcall.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func"), FunctionDescriptor.ofVoid(C_POINTER)); - handle.invokeExact((Addressable)upcall); + handle.invokeExact(upcall); } static void dummy() { } @@ -141,9 +149,9 @@ public void testClosedVaListCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { - VaList list = VaList.make(b -> b.addVarg(C_INT, 42), session); - handle.invoke(list, sessionChecker(session)); + try (Arena arena = Arena.openConfined()) { + VaList list = VaList.make(b -> b.addVarg(C_INT, 42), arena.scope()); + handle.invokeExact(list.segment(), sessionChecker(arena)); } } @@ -153,9 +161,9 @@ public void testClosedStructCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(POINT, session); - handle.invoke(segment, sessionChecker(session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(POINT); + handle.invokeExact(segment, sessionChecker(arena)); } } @@ -165,27 +173,27 @@ public void testClosedUpcallCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); - MemorySegment upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), session); - handle.invoke(upcall, sessionChecker(session)); + MemorySegment upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), arena.scope()); + handle.invokeExact(upcall, sessionChecker(arena)); } } - MemorySegment sessionChecker(MemorySession session) { + MemorySegment sessionChecker(Arena arena) { try { MethodHandle handle = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "checkSession", - MethodType.methodType(void.class, MemorySession.class)); - handle = handle.bindTo(session); - return Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), MemorySession.openImplicit()); + MethodType.methodType(void.class, Arena.class)); + handle = handle.bindTo(arena); + return Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), SegmentScope.auto()); } catch (Throwable ex) { throw new AssertionError(ex); } } - static void checkSession(MemorySession session) { + static void checkSession(Arena arena) { try { - session.close(); + arena.close(); fail("Session closed unexpectedly!"); } catch (IllegalStateException ex) { assertTrue(ex.getMessage().contains("acquired")); //if acquired, fine diff --git a/test/jdk/java/foreign/StdLibTest.java b/test/jdk/java/foreign/StdLibTest.java index 98bf9f50703..05c4faac992 100644 --- a/test/jdk/java/foreign/StdLibTest.java +++ b/test/jdk/java/foreign/StdLibTest.java @@ -152,37 +152,35 @@ void test_vprintf(List args) throws Throwable { static class StdLibHelper { - final static MethodHandle strcat = abi.downcallHandle(abi.defaultLookup().lookup("strcat").get(), - FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)) - .asType(MethodType.methodType(MemoryAddress.class, MemorySegment.class, MemorySegment.class)); // exact signature match + final static MethodHandle strcat = abi.downcallHandle(abi.defaultLookup().find("strcat").get(), + FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)); - - final static MethodHandle strcmp = abi.downcallHandle(abi.defaultLookup().lookup("strcmp").get(), + final static MethodHandle strcmp = abi.downcallHandle(abi.defaultLookup().find("strcmp").get(), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static MethodHandle puts = abi.downcallHandle(abi.defaultLookup().lookup("puts").get(), + final static MethodHandle puts = abi.downcallHandle(abi.defaultLookup().find("puts").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle strlen = abi.downcallHandle(abi.defaultLookup().lookup("strlen").get(), + final static MethodHandle strlen = abi.downcallHandle(abi.defaultLookup().find("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle gmtime = abi.downcallHandle(abi.defaultLookup().lookup("gmtime").get(), + final static MethodHandle gmtime = abi.downcallHandle(abi.defaultLookup().find("gmtime").get(), FunctionDescriptor.of(C_POINTER, C_POINTER)); - final static MethodHandle qsort = abi.downcallHandle(abi.defaultLookup().lookup("qsort").get(), + final static MethodHandle qsort = abi.downcallHandle(abi.defaultLookup().find("qsort").get(), FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER)); final static FunctionDescriptor qsortComparFunction = FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER); final static MethodHandle qsortCompar; - final static MethodHandle rand = abi.downcallHandle(abi.defaultLookup().lookup("rand").get(), + final static MethodHandle rand = abi.downcallHandle(abi.defaultLookup().find("rand").get(), FunctionDescriptor.of(C_INT)); - final static MethodHandle vprintf = abi.downcallHandle(abi.defaultLookup().lookup("vprintf").get(), + final static MethodHandle vprintf = abi.downcallHandle(abi.defaultLookup().find("vprintf").get(), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static Addressable printfAddr = abi.defaultLookup().lookup("printf").get(); + final static MemorySegment printfAddr = abi.defaultLookup().find("printf").get(); final static FunctionDescriptor printfBase = FunctionDescriptor.of(C_INT, C_POINTER); @@ -190,48 +188,48 @@ static class StdLibHelper { try { //qsort upcall handle qsortCompar = MethodHandles.lookup().findStatic(StdLibTest.StdLibHelper.class, "qsortCompare", - Linker.upcallType(qsortComparFunction)); + qsortComparFunction.toMethodType()); } catch (ReflectiveOperationException ex) { throw new IllegalStateException(ex); } } String strcat(String s1, String s2) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment buf = session.allocate(s1.length() + s2.length() + 1); + try (var arena = Arena.openConfined()) { + MemorySegment buf = arena.allocate(s1.length() + s2.length() + 1); buf.setUtf8String(0, s1); - MemorySegment other = session.allocateUtf8String(s2); - return ((MemoryAddress)strcat.invokeExact(buf, other)).getUtf8String(0); + MemorySegment other = arena.allocateUtf8String(s2); + return ((MemorySegment)strcat.invokeExact(buf, other)).getUtf8String(0); } } int strcmp(String s1, String s2) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment ns1 = session.allocateUtf8String(s1); - MemorySegment ns2 = session.allocateUtf8String(s2); - return (int)strcmp.invoke(ns1, ns2); + try (var arena = Arena.openConfined()) { + MemorySegment ns1 = arena.allocateUtf8String(s1); + MemorySegment ns2 = arena.allocateUtf8String(s2); + return (int)strcmp.invokeExact(ns1, ns2); } } int puts(String msg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = session.allocateUtf8String(msg); - return (int)puts.invoke(s); + try (var arena = Arena.openConfined()) { + MemorySegment s = arena.allocateUtf8String(msg); + return (int)puts.invokeExact(s); } } int strlen(String msg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = session.allocateUtf8String(msg); - return (int)strlen.invoke(s); + try (var arena = Arena.openConfined()) { + MemorySegment s = arena.allocateUtf8String(msg); + return (int)strlen.invokeExact(s); } } Tm gmtime(long arg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment time = session.allocate(8); + try (var arena = Arena.openConfined()) { + MemorySegment time = arena.allocate(8); time.set(C_LONG_LONG, 0, arg); - return new Tm((MemoryAddress)gmtime.invoke(time)); + return new Tm((MemorySegment)gmtime.invokeExact(time)); } } @@ -242,8 +240,8 @@ static class Tm { static final long SIZE = 56; - Tm(MemoryAddress addr) { - this.base = MemorySegment.ofAddress(addr, SIZE, MemorySession.global()); + Tm(MemorySegment addr) { + this.base = addr.asSlice(0, SIZE); } int sec() { @@ -277,20 +275,20 @@ boolean isdst() { int[] qsort(int[] arr) throws Throwable { //init native array - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArr = session.allocateArray(C_INT, arr); + try (var arena = Arena.openConfined()) { + MemorySegment nativeArr = arena.allocateArray(C_INT, arr); //call qsort - Addressable qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, session); + MemorySegment qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, arena.scope()); - qsort.invoke(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); + qsort.invokeExact(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); //convert back to Java array return nativeArr.toArray(C_INT); } } - static int qsortCompare(MemoryAddress addr1, MemoryAddress addr2) { + static int qsortCompare(MemorySegment addr1, MemorySegment addr2) { return addr1.get(C_INT, 0) - addr2.get(C_INT, 0); } @@ -300,32 +298,34 @@ int rand() throws Throwable { } int printf(String format, List args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment formatStr = session.allocateUtf8String(format); - return (int)specializedPrintf(args).invoke(formatStr, - args.stream().map(a -> a.nativeValue(session)).toArray()); + try (var arena = Arena.openConfined()) { + MemorySegment formatStr = arena.allocateUtf8String(format); + return (int)specializedPrintf(args).invokeExact(formatStr, + args.stream().map(a -> a.nativeValue(arena)).toArray()); } } int vprintf(String format, List args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment formatStr = session.allocateUtf8String(format); - VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, session)), session); - return (int)vprintf.invoke(formatStr, vaList); + try (var arena = Arena.openConfined()) { + MemorySegment formatStr = arena.allocateUtf8String(format); + VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, arena)), arena.scope()); + return (int)vprintf.invokeExact(formatStr, vaList.segment()); } } private MethodHandle specializedPrintf(List args) { //method type - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(int.class, MemorySegment.class); FunctionDescriptor fd = printfBase; List variadicLayouts = new ArrayList<>(args.size()); for (PrintfArg arg : args) { mt = mt.appendParameterTypes(arg.carrier); variadicLayouts.add(arg.layout); } + Linker.Option varargIndex = Linker.Option.firstVariadicArg(fd.argumentLayouts().size()); MethodHandle mh = abi.downcallHandle(printfAddr, - fd.asVariadic(variadicLayouts.toArray(new MemoryLayout[args.size()]))); + fd.appendArgumentLayouts(variadicLayouts.toArray(new MemoryLayout[args.size()])), + varargIndex); return mh.asSpreader(1, Object[].class, args.size()); } } @@ -384,26 +384,24 @@ public static Object[][] printfArgs() { .toArray(Object[][]::new); } - enum PrintfArg implements BiConsumer { + enum PrintfArg implements BiConsumer { - INTEGRAL(int.class, C_INT, "%d", session -> 42, 42, VaList.Builder::addVarg), - STRING(MemoryAddress.class, C_POINTER, "%s", session -> { - var segment = MemorySegment.allocateNative(4, session); - segment.setUtf8String(0, "str"); - return segment.address(); + INTEGRAL(int.class, C_INT, "%d", arena -> 42, 42, VaList.Builder::addVarg), + STRING(MemorySegment.class, C_POINTER, "%s", arena -> { + return arena.allocateUtf8String("str"); }, "str", VaList.Builder::addVarg), - CHAR(byte.class, C_CHAR, "%c", session -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)), - DOUBLE(double.class, C_DOUBLE, "%.4f", session ->1.2345d, 1.2345d, VaList.Builder::addVarg); + CHAR(byte.class, C_CHAR, "%c", arena -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)), + DOUBLE(double.class, C_DOUBLE, "%.4f", arena ->1.2345d, 1.2345d, VaList.Builder::addVarg); final Class carrier; final ValueLayout layout; final String format; - final Function nativeValueFactory; + final Function nativeValueFactory; final Object javaValue; @SuppressWarnings("rawtypes") final VaListBuilderCall builderCall; - PrintfArg(Class carrier, L layout, String format, Function nativeValueFactory, Object javaValue, VaListBuilderCall builderCall) { + PrintfArg(Class carrier, L layout, String format, Function nativeValueFactory, Object javaValue, VaListBuilderCall builderCall) { this.carrier = carrier; this.layout = layout; this.format = format; @@ -414,16 +412,16 @@ PrintfArg(Class carrier, L layout, String format, @Override @SuppressWarnings("unchecked") - public void accept(VaList.Builder builder, MemorySession session) { - builderCall.build(builder, layout, nativeValueFactory.apply(session)); + public void accept(VaList.Builder builder, Arena arena) { + builderCall.build(builder, layout, nativeValueFactory.apply(arena)); } interface VaListBuilderCall { void build(VaList.Builder builder, L layout, V value); } - public Object nativeValue(MemorySession session) { - return nativeValueFactory.apply(session); + public Object nativeValue(Arena arena) { + return nativeValueFactory.apply(arena); } } diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index c16701991c6..de74ed8c6b2 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -31,8 +31,9 @@ * @run testng/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.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -93,7 +94,7 @@ public class TestAdaptVarHandles { @Test public void testFilterValue() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, S2I, I2S); i2SHandle.set(segment, "1"); @@ -112,7 +113,7 @@ public void testFilterValue() throws Throwable { @Test public void testFilterValueComposite() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); MethodHandle CTX_S2I = MethodHandles.dropArguments(S2I, 0, String.class, String.class); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, CTX_S2I, CTX_I2S); @@ -133,7 +134,7 @@ public void testFilterValueComposite() throws Throwable { @Test public void testFilterValueLoose() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, O2I, I2O); i2SHandle.set(segment, "1"); @@ -190,8 +191,8 @@ public void testBadFilterUnboxException() { public void testBadFilterBoxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I, I2S_EX); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, arena.scope()); vh.set(seg, "42"); String x = (String) vh.get(seg); // should throw } @@ -201,8 +202,8 @@ public void testBadFilterBoxHandleException() { public void testBadFilterUnboxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I_EX, I2S); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, arena.scope()); vh.set(seg, "42"); // should throw } } @@ -210,7 +211,7 @@ public void testBadFilterUnboxHandleException() { @Test public void testFilterCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); 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); @@ -253,7 +254,7 @@ public void testBadFilterCoordinatesTooManyFilters() { @Test public void testInsertCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_longIndex = MethodHandles.insertCoordinates(intHandleIndexed, 0, segment, 0L); intHandle_longIndex.set(1); int oldValue = (int)intHandle_longIndex.getAndAdd(42); @@ -291,7 +292,7 @@ public void testBadInsertCoordinatesTooManyValues() { @Test public void testPermuteCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_swap = MethodHandles.permuteCoordinates(intHandleIndexed, List.of(long.class, MemorySegment.class), 1, 0); intHandle_swap.set(0L, segment, 1); @@ -330,7 +331,7 @@ public void testBadPermuteCoordinatesIndexTooSmall() { @Test public void testCollectCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); 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); @@ -373,7 +374,7 @@ public void testBadCollectCoordinatesWrongFilterException() { @Test public void testDropCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); 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); diff --git a/test/jdk/java/foreign/TestArrays.java b/test/jdk/java/foreign/TestArrays.java index 978993e1fb1..e16dfb0d851 100644 --- a/test/jdk/java/foreign/TestArrays.java +++ b/test/jdk/java/foreign/TestArrays.java @@ -28,11 +28,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrays */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.invoke.VarHandle; @@ -108,7 +108,7 @@ static void checkBytes(MemorySegment base, SequenceLayout layout, Function init, Consumer checker, MemoryLayout layout) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); init.accept(segment); assertFalse(segment.isReadOnly()); checker.accept(segment); @@ -119,7 +119,7 @@ public void testArrays(Consumer init, Consumer che 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.ofAddress(MemoryAddress.NULL, seq.byteSize(), MemorySession.global()); + MemorySegment segment = MemorySegment.ofAddress(0, seq.byteSize(), SegmentScope.global()); arrayFactory.apply(segment); } @@ -127,8 +127,8 @@ public void testTooBigForArray(MemoryLayout layout, Function arrayFactory) { if (layout.byteSize() == 1) throw new IllegalStateException(); //make it fail - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout.byteSize() + 1, layout.byteSize(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout.byteSize() + 1, layout.byteSize(), arena.scope()); arrayFactory.apply(segment); } } @@ -136,8 +136,9 @@ public void testBadSize(MemoryLayout layout, Function arr @Test(dataProvider = "elemLayouts", expectedExceptions = IllegalStateException.class) public void testArrayFromClosedSegment(MemoryLayout layout, Function arrayFactory) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openConfined()); - segment.session().close(); + Arena arena = Arena.openConfined(); + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); + arena.close(); arrayFactory.apply(segment); } diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index 998a3197548..4f13b9112e6 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -28,11 +28,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestByteBuffer */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout.PathElement; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.io.File; @@ -63,7 +63,6 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -186,8 +185,8 @@ static void checkBytes(MemorySegment base, SequenceLayout lay @Test public void testOffheap() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(tuples, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(tuples, arena.scope());; initTuples(segment, tuples.elementCount()); ByteBuffer bb = segment.asByteBuffer(); @@ -231,15 +230,15 @@ public void testChannel() throws Throwable { @Test public void testDefaultAccessModesMappedSegment() throws Throwable { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena.scope()); assertFalse(segment.isReadOnly()); } - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, arena.scope()); assertTrue(segment.isReadOnly()); } } @@ -250,18 +249,18 @@ public void testMappedSegment() throws Throwable { f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { //write to channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), arena.scope()); initTuples(segment, tuples.elementCount()); segment.force(); } - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { //read from channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena.scope()); checkTuples(segment, segment.asByteBuffer(), tuples.elementCount()); } } @@ -272,11 +271,11 @@ public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws T f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); - FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, session); + Arena arena = Arena.openConfined(); + try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena.scope()); assertTrue(segment.isMapped()); - segment.session().close(); + arena.close(); mappedBufferOp.apply(segment); } } @@ -291,10 +290,10 @@ public void testMappedSegmentOffset() throws Throwable { // write one at a time for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { //write to channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), arena.scope()); initTuples(segment, 1); segment.force(); } @@ -302,10 +301,10 @@ public void testMappedSegmentOffset() throws Throwable { // check one at a time for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { //read from channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena.scope()); checkTuples(segment, segment.asByteBuffer(), 1); } } @@ -323,9 +322,9 @@ public void testLargeMappedSegment() throws Throwable { f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, arena.scope()); segment.isLoaded(); segment.load(); segment.isLoaded(); @@ -361,8 +360,8 @@ static void checkByteArrayAlignment(MemoryLayout layout) { @Test(dataProvider = "bufferOps") public void testScopedBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { Buffer bb; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; bb = bufferFactory.apply(segment.asByteBuffer()); } //outside of session!! @@ -387,8 +386,8 @@ public void testScopedBuffer(Function bufferFactory, @NoInje @Test(dataProvider = "bufferHandleOps") public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { ByteBuffer bb; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; bb = segment.asByteBuffer(); for (Map.Entry e : varHandleMembers(bb, bufferHandle).entrySet()) { MethodHandle handle = e.getKey().bindTo(bufferHandle) @@ -421,12 +420,12 @@ public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { @Test(dataProvider = "bufferOps") public void testDirectBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; Buffer bb = bufferFactory.apply(segment.asByteBuffer()); assertTrue(bb.isDirect()); DirectBuffer directBuffer = ((DirectBuffer)bb); - assertEquals(directBuffer.address(), segment.address().toRawLongValue()); + assertEquals(directBuffer.address(), segment.address()); assertTrue((directBuffer.attachment() == null) == (bb instanceof ByteBuffer)); assertTrue(directBuffer.cleaner() == null); } @@ -434,8 +433,8 @@ public void testDirectBuffer(Function bufferFactory, @NoInje @Test(dataProvider="resizeOps") public void testResizeOffheap(Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); checker.accept(segment); } @@ -472,8 +471,8 @@ public void testResizeRoundtripHeap(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer()); checker.accept(second); @@ -483,8 +482,8 @@ public void testResizeRoundtripNative(Consumer checker, Consumer< @Test(expectedExceptions = IllegalStateException.class) public void testBufferOnClosedSession() { MemorySegment leaked; - try (MemorySession session = MemorySession.openConfined()) { - leaked = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + leaked = MemorySegment.allocateNative(bytes, arena.scope());; } ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok byteBuffer.get(); // should throw @@ -492,7 +491,7 @@ public void testBufferOnClosedSession() { @Test(expectedExceptions = IllegalStateException.class) public void testTooBigForByteBuffer() { - MemorySegment segment = MemorySegment.ofAddress(MemoryAddress.NULL, Integer.MAX_VALUE + 10L, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.ofAddress(0, Integer.MAX_VALUE + 10L, SegmentScope.auto()); segment.asByteBuffer(); } @@ -502,7 +501,7 @@ public void testBadMapNegativeSize() throws IOException { f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, SegmentScope.auto()); } } @@ -512,7 +511,7 @@ public void testBadMapNegativeOffset() throws IOException { f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, SegmentScope.auto()); } } @@ -524,9 +523,9 @@ public void testMapOffset() throws IOException { int SIZE = Byte.MAX_VALUE; - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, arena.scope()); for (byte offset = 0; offset < SIZE; offset++) { segment.set(JAVA_BYTE, offset, offset); } @@ -534,9 +533,9 @@ public void testMapOffset() throws IOException { } for (int offset = 0 ; offset < SIZE ; offset++) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, arena.scope()); assertEquals(segment.get(JAVA_BYTE, 0), offset); } } @@ -548,9 +547,9 @@ public void testMapZeroSize() throws IOException { f.createNewFile(); f.deleteOnExit(); //RW - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, arena.scope()); assertEquals(segment.byteSize(), 0); assertEquals(segment.isMapped(), true); assertFalse(segment.isReadOnly()); @@ -560,9 +559,9 @@ public void testMapZeroSize() throws IOException { segment.unload(); } //RO - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, arena.scope()); assertEquals(segment.byteSize(), 0); assertEquals(segment.isMapped(), true); assertTrue(segment.isReadOnly()); @@ -577,7 +576,7 @@ public void testMapZeroSize() throws IOException { public void testMapCustomPath() throws IOException { Path path = Path.of(URI.create("jrt:/")); try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, SegmentScope.auto()); } } @@ -585,8 +584,8 @@ public void testMapCustomPath() throws IOException { public void testCopyHeapToNative(Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArray = MemorySegment.allocateNative(bytes, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment nativeArray = MemorySegment.allocateNative(bytes, 1, arena.scope());; MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); initializer.accept(heapArray); nativeArray.copyFrom(heapArray); @@ -598,8 +597,8 @@ public void testCopyHeapToNative(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArray = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment nativeArray = MemorySegment.allocateNative(seq, arena.scope());; MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); initializer.accept(nativeArray); heapArray.copyFrom(nativeArray); @@ -670,8 +669,8 @@ public void bufferProperties(ByteBuffer bb, Predicate _unused) { @Test public void testRoundTripAccess() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment ms = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment ms = MemorySegment.allocateNative(4, 1, arena.scope());; MemorySegment msNoAccess = ms.asReadOnly(); MemorySegment msRoundTrip = MemorySegment.ofBuffer(msNoAccess.asByteBuffer()); assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly()); @@ -680,23 +679,23 @@ public void testRoundTripAccess() { @Test(expectedExceptions = IllegalStateException.class) public void testDeadAccessOnClosedBufferSegment() { - MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, MemorySession.openConfined()); + Arena arena = Arena.openConfined(); + MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, arena.scope()); MemorySegment s2 = MemorySegment.ofBuffer(s1.asByteBuffer()); // memory freed - s1.session().close(); + arena.close(); s2.set(JAVA_INT, 0, 10); // Dead access! } - @Test(dataProvider = "allSessions") - public void testIOOnSegmentBuffer(Supplier sessionSupplier) throws IOException { + @Test(dataProvider = "closeableArenas") + public void closeableArenas(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); - MemorySession session; try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ; - MemorySession scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment = MemorySegment.allocateNative(10, 1, session); + Arena arena = arenaSupplier.get()) { + MemorySegment segment = MemorySegment.allocateNative(10, 1, arena.scope());; for (int i = 0; i < 10; i++) { segment.set(JAVA_BYTE, i, (byte) i); } @@ -711,17 +710,18 @@ public void testIOOnSegmentBuffer(Supplier sessionSupplier) throw static final Class ISE = IllegalStateException.class; - @Test(dataProvider = "closeableSessions") - public void testIOOnClosedSegmentBuffer(Supplier sessionSupplier) throws IOException { + @Test(dataProvider = "closeableArenas") + public void testIOOnClosedSegmentBuffer(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); + Arena arena = arenaSupplier.get(); try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = MemorySegment.allocateNative(10, sessionSupplier.get()); + MemorySegment segment = MemorySegment.allocateNative(10, arena.scope()); for (int i = 0; i < 10; i++) { segment.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb = segment.asByteBuffer(); - segment.session().close(); + arena.close(); assertThrows(ISE, () -> channel.read(bb)); assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})); assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)); @@ -733,8 +733,8 @@ public void testIOOnClosedSegmentBuffer(Supplier sessionSupplier) @Test public void buffersAndArraysFromSlices() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(16, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(16, arena.scope());; int newSize = 8; var slice = segment.asSlice(4, newSize); @@ -751,8 +751,8 @@ public void buffersAndArraysFromSlices() { @Test public void viewsFromSharedSegment() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(16, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(16, arena.scope());; var byteBuffer = segment.asByteBuffer(); byteBuffer.asReadOnlyBuffer(); byteBuffer.slice(0, 8); @@ -762,33 +762,20 @@ public void viewsFromSharedSegment() { @DataProvider(name = "segments") public static Object[][] segments() throws Throwable { return new Object[][] { - { (Supplier) () -> MemorySegment.allocateNative(16, MemorySession.openImplicit()) }, - { (Supplier) () -> MemorySegment.allocateNative(16, MemorySession.openConfined()) }, + { (Supplier) () -> MemorySegment.allocateNative(16, SegmentScope.auto()) }, + { (Supplier) () -> MemorySegment.allocateNative(16, Arena.openConfined().scope()) }, { (Supplier) () -> MemorySegment.ofArray(new byte[16]) } }; } - @DataProvider(name = "closeableSessions") - public static Object[][] closeableSessions() { + @DataProvider(name = "closeableArenas") + public static Object[][] closeableArenas() { return new Object[][] { - { (Supplier) () -> MemorySession.openShared() }, - { (Supplier) () -> MemorySession.openConfined() }, - { (Supplier) () -> MemorySession.openShared(Cleaner.create()) }, - { (Supplier) () -> MemorySession.openConfined(Cleaner.create()) }, + { (Supplier) Arena::openConfined }, + { (Supplier) Arena::openShared }, }; } - @DataProvider(name = "allSessions") - public static Object[][] allSessions() { - return Stream.of(new Object[][] { { (Supplier) MemorySession::global} }, closeableSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - static MemorySession closeableSessionOrNull(MemorySession session) { - return session.isCloseable() ? session : null; - } - @DataProvider(name = "bufferOps") public static Object[][] bufferOps() throws Throwable { List args = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestClassLoaderFindNative.java b/test/jdk/java/foreign/TestClassLoaderFindNative.java index d83ca5bea9b..b462180b135 100644 --- a/test/jdk/java/foreign/TestClassLoaderFindNative.java +++ b/test/jdk/java/foreign/TestClassLoaderFindNative.java @@ -29,7 +29,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; import org.testng.annotations.Test; @@ -49,20 +49,20 @@ public class TestClassLoaderFindNative { @Test public void testSimpleLookup() { - assertFalse(SymbolLookup.loaderLookup().lookup("f").isEmpty()); + assertFalse(SymbolLookup.loaderLookup().find("f").isEmpty()); } @Test public void testInvalidSymbolLookup() { - assertTrue(SymbolLookup.loaderLookup().lookup("nonExistent").isEmpty()); + assertTrue(SymbolLookup.loaderLookup().find("nonExistent").isEmpty()); } @Test public void testVariableSymbolLookup() { MemorySegment segment = MemorySegment.ofAddress( - SymbolLookup.loaderLookup().lookup("c").get().address(), + SymbolLookup.loaderLookup().find("c").get().address(), ValueLayout.JAVA_INT.byteSize(), - MemorySession.global()); + SegmentScope.global()); assertEquals(segment.get(JAVA_BYTE, 0), 42); } } diff --git a/test/jdk/java/foreign/TestDowncallBase.java b/test/jdk/java/foreign/TestDowncallBase.java index 3e992228a6a..14d8928afc8 100644 --- a/test/jdk/java/foreign/TestDowncallBase.java +++ b/test/jdk/java/foreign/TestDowncallBase.java @@ -22,9 +22,9 @@ * */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; import java.lang.foreign.SegmentAllocator; import java.lang.invoke.MethodHandle; @@ -36,7 +36,7 @@ public class TestDowncallBase extends CallGeneratorHelper { static Linker LINKER = Linker.nativeLinker(); - Object doCall(Addressable symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { + Object doCall(MemorySegment symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { MethodHandle mh = downcallHandle(LINKER, symbol, allocator, descriptor); Object res = mh.invokeWithArguments(args); return res; diff --git a/test/jdk/java/foreign/TestDowncallScope.java b/test/jdk/java/foreign/TestDowncallScope.java index 67e63273e0c..1d586274ff1 100644 --- a/test/jdk/java/foreign/TestDowncallScope.java +++ b/test/jdk/java/foreign/TestDowncallScope.java @@ -38,11 +38,10 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.util.ArrayList; import java.util.List; @@ -61,20 +60,20 @@ public void testDowncall(int count, String fName, CallGeneratorHelper.Ret ret, List paramTypes, List fields) throws Throwable { List> checks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); + MemorySegment addr = findNativeOrThrow(fName); FunctionDescriptor descriptor = function(ret, paramTypes, fields); Object[] args = makeArgs(paramTypes, fields, checks); - try (MemorySession session = MemorySession.openShared()) { + try (Arena arena = Arena.openShared()) { boolean needsScope = descriptor.returnLayout().map(GroupLayout.class::isInstance).orElse(false); SegmentAllocator allocator = needsScope ? - SegmentAllocator.newNativeArena(session) : + SegmentAllocator.nativeAllocator(arena.scope()) : THROWING_ALLOCATOR; Object res = doCall(addr, allocator, descriptor, args); if (ret == CallGeneratorHelper.Ret.NON_VOID) { checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).session(), session); + assertEquals(((MemorySegment)res).scope(), arena.scope()); } } } diff --git a/test/jdk/java/foreign/TestDowncallStack.java b/test/jdk/java/foreign/TestDowncallStack.java index abf7d32b968..1426604a931 100644 --- a/test/jdk/java/foreign/TestDowncallStack.java +++ b/test/jdk/java/foreign/TestDowncallStack.java @@ -34,11 +34,10 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.util.ArrayList; import java.util.List; @@ -57,20 +56,20 @@ public void testDowncallStack(int count, String fName, CallGeneratorHelper.Ret r List paramTypes, List fields) throws Throwable { List> checks = new ArrayList<>(); - Addressable addr = findNativeOrThrow("s" + fName); + MemorySegment addr = findNativeOrThrow("s" + fName); FunctionDescriptor descriptor = functionStack(ret, paramTypes, fields); Object[] args = makeArgsStack(paramTypes, fields, checks); - try (MemorySession session = MemorySession.openShared()) { + try (Arena arena = Arena.openShared()) { boolean needsScope = descriptor.returnLayout().map(GroupLayout.class::isInstance).orElse(false); SegmentAllocator allocator = needsScope ? - SegmentAllocator.newNativeArena(session) : + SegmentAllocator.nativeAllocator(arena.scope()) : THROWING_ALLOCATOR; Object res = doCall(addr, allocator, descriptor, args); if (ret == CallGeneratorHelper.Ret.NON_VOID) { checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).session(), session); + assertEquals(((MemorySegment)res).scope(), arena.scope()); } } } diff --git a/test/jdk/java/foreign/TestFallbackLookup.java b/test/jdk/java/foreign/TestFallbackLookup.java index d129db228c5..71363590b9a 100644 --- a/test/jdk/java/foreign/TestFallbackLookup.java +++ b/test/jdk/java/foreign/TestFallbackLookup.java @@ -38,6 +38,6 @@ public class TestFallbackLookup { void testBadSystemLookupRequest() { // we request a Linker, forcing OS name to be "Windows". This should trigger an exception when // attempting to load a non-existent ucrtbase.dll. Make sure that no error is generated at this stage. - assertTrue(Linker.nativeLinker().defaultLookup().lookup("nonExistentSymbol").isEmpty()); + assertTrue(Linker.nativeLinker().defaultLookup().find("nonExistentSymbol").isEmpty()); } } diff --git a/test/jdk/java/foreign/TestFree.java b/test/jdk/java/foreign/TestFree.java index 2a5dcac2796..a61499a2194 100644 --- a/test/jdk/java/foreign/TestFree.java +++ b/test/jdk/java/foreign/TestFree.java @@ -30,25 +30,17 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFree */ -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import static org.testng.Assert.assertEquals; public class TestFree extends NativeTestHelper { - private static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements) { - return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), MemorySession.global()); - } - public void test() throws Throwable { String str = "hello world"; - MemoryAddress addr = allocateMemory(str.length() + 1); - MemorySegment seg = asArray(addr, C_CHAR, str.length() + 1); - seg.copyFrom(MemorySegment.ofArray(str.getBytes())); - seg.set(C_CHAR, str.length(), (byte)0); - assertEquals(str, seg.getUtf8String(0)); + MemorySegment addr = allocateMemory(str.length() + 1); + addr.copyFrom(MemorySegment.ofArray(str.getBytes())); + addr.set(C_CHAR, str.length(), (byte)0); + assertEquals(str, addr.getUtf8String(0)); freeMemory(addr); } } diff --git a/test/jdk/java/foreign/TestFunctionDescriptor.java b/test/jdk/java/foreign/TestFunctionDescriptor.java index 2438ce23c48..915c97ad507 100644 --- a/test/jdk/java/foreign/TestFunctionDescriptor.java +++ b/test/jdk/java/foreign/TestFunctionDescriptor.java @@ -31,6 +31,8 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodType; import java.util.List; import java.util.Optional; import org.testng.annotations.Test; @@ -98,10 +100,25 @@ public void testDropReturnLayout() { @Test public void testEquals() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - FunctionDescriptor fd_va1 = FunctionDescriptor.of(C_INT).asVariadic(C_INT, C_INT); - FunctionDescriptor fd_va2 = FunctionDescriptor.of(C_INT, C_INT).asVariadic(C_INT); assertEquals(fd, fd); - assertNotEquals(fd, fd_va1); - assertNotEquals(fd, fd_va2); + } + + @Test + public void testCarrierMethodType() { + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, + C_INT, + MemoryLayout.structLayout(C_INT, C_INT)); + MethodType cmt = fd.toMethodType(); + assertEquals(cmt, MethodType.methodType(int.class, int.class, MemorySegment.class)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testBadCarrierMethodType() { + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, + C_INT, + MemoryLayout.structLayout(C_INT, C_INT), + MemoryLayout.sequenceLayout(3, C_INT), + MemoryLayout.paddingLayout(32)); + fd.toMethodType(); // should throw } } diff --git a/test/jdk/java/foreign/TestHandshake.java b/test/jdk/java/foreign/TestHandshake.java index 8d33b5b64ce..519739cb1eb 100644 --- a/test/jdk/java/foreign/TestHandshake.java +++ b/test/jdk/java/foreign/TestHandshake.java @@ -32,8 +32,8 @@ * @run testng/othervm -XX:-TieredCompilation TestHandshake */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; @@ -67,8 +67,8 @@ public class TestHandshake { @Test(dataProvider = "accessors") public void testHandshake(String testName, AccessorFactory accessorFactory) throws InterruptedException { for (int it = 0 ; it < ITERATIONS ; it++) { - MemorySession session = MemorySession.openShared(); - MemorySegment segment = MemorySegment.allocateNative(SEGMENT_SIZE, 1, session); + Arena arena = Arena.openShared(); + MemorySegment segment = MemorySegment.allocateNative(SEGMENT_SIZE, 1, arena.scope()); System.out.println("ITERATION " + it); ExecutorService accessExecutor = Executors.newCachedThreadPool(); start.set(System.currentTimeMillis()); @@ -79,10 +79,10 @@ public void testHandshake(String testName, AccessorFactory accessorFactory) thro int delay = ThreadLocalRandom.current().nextInt(MAX_DELAY_MILLIS); System.out.println("Starting handshaker with delay set to " + delay + " millis"); Thread.sleep(delay); - accessExecutor.execute(new Handshaker(session)); + accessExecutor.execute(new Handshaker(arena)); accessExecutor.shutdown(); assertTrue(accessExecutor.awaitTermination(MAX_EXECUTOR_WAIT_SECONDS, TimeUnit.SECONDS)); - assertTrue(!segment.session().isAlive()); + assertTrue(!segment.scope().isAlive()); } } @@ -99,7 +99,7 @@ static abstract class AbstractSegmentAccessor implements Runnable { @Override public final void run() { start("\"Accessor #\" + id"); - outer: while (segment.session().isAlive()) { + outer: while (segment.scope().isAlive()) { try { doAccess(); } catch (IllegalStateException ex) { @@ -193,7 +193,7 @@ static class SegmentMismatchAccessor extends AbstractSegmentAccessor { SegmentMismatchAccessor(int id, MemorySegment segment) { super(id, segment); - this.copy = MemorySegment.allocateNative(SEGMENT_SIZE, 1, segment.session()); + this.copy = MemorySegment.allocateNative(SEGMENT_SIZE, 1, segment.scope()); copy.copyFrom(segment); copy.set(JAVA_BYTE, ThreadLocalRandom.current().nextInt(SEGMENT_SIZE), (byte)42); } @@ -238,10 +238,10 @@ public void doAccess() { static class Handshaker implements Runnable { - final MemorySession session; + final Arena arena; - Handshaker(MemorySession session) { - this.session = session; + Handshaker(Arena arena) { + this.arena = arena; } @Override @@ -249,7 +249,7 @@ public void run() { start("Handshaker"); while (true) { try { - session.close(); + arena.close(); break; } catch (IllegalStateException ex) { Thread.onSpinWait(); diff --git a/test/jdk/java/foreign/TestHeapAlignment.java b/test/jdk/java/foreign/TestHeapAlignment.java index 91a15453816..eff8dca9802 100644 --- a/test/jdk/java/foreign/TestHeapAlignment.java +++ b/test/jdk/java/foreign/TestHeapAlignment.java @@ -29,10 +29,9 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment */ -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import java.util.ArrayList; import java.util.List; @@ -101,7 +100,7 @@ enum SegmentAndAlignment { HEAP_FLOAT(MemorySegment.ofArray(new float[2]), 4), HEAP_LONG(MemorySegment.ofArray(new long[1]), 8), HEAP_DOUBLE(MemorySegment.ofArray(new double[1]), 8), - NATIVE(MemorySegment.allocateNative(8, MemorySession.openImplicit()), -1); + NATIVE(MemorySegment.allocateNative(8, SegmentScope.auto()), -1); final MemorySegment segment; final int align; @@ -124,7 +123,7 @@ public static Object[][] layouts() { layouts.add(new Object[] { testCase.segment, testCase.align, 42f, new float[]{42}, JAVA_FLOAT_ALIGNED, (Function)MemorySegment::ofArray }); layouts.add(new Object[] { testCase.segment, testCase.align, 42L, new long[]{42}, JAVA_LONG_ALIGNED, (Function)MemorySegment::ofArray }); layouts.add(new Object[] { testCase.segment, testCase.align, 42d, new double[]{42}, JAVA_DOUBLE_ALIGNED, (Function)MemorySegment::ofArray }); - layouts.add(new Object[] { testCase.segment, testCase.align, MemoryAddress.ofLong(42), null, ADDRESS_ALIGNED, null }); + layouts.add(new Object[] { testCase.segment, testCase.align, MemorySegment.ofAddress(42), null, ADDRESS_ALIGNED, null }); } return layouts.toArray(new Object[0][]); } diff --git a/test/jdk/java/foreign/TestIllegalLink.java b/test/jdk/java/foreign/TestIllegalLink.java index 3219d150158..670ac641eb2 100644 --- a/test/jdk/java/foreign/TestIllegalLink.java +++ b/test/jdk/java/foreign/TestIllegalLink.java @@ -29,11 +29,12 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; +import java.nio.ByteOrder; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -42,7 +43,7 @@ public class TestIllegalLink extends NativeTestHelper { - private static final Addressable DUMMY_TARGET = MemoryAddress.ofLong(1); + private static final MemorySegment DUMMY_TARGET = MemorySegment.ofAddress(1); private static final Linker ABI = Linker.nativeLinker(); @Test(dataProvider = "types") @@ -51,7 +52,8 @@ public void testTypeMismatch(FunctionDescriptor desc, String expectedExceptionMe ABI.downcallHandle(DUMMY_TARGET, desc); fail("Expected IllegalArgumentException was not thrown"); } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains(expectedExceptionMessage)); + assertTrue(e.getMessage().contains(expectedExceptionMessage), + e.getMessage() + " != " + expectedExceptionMessage); } } @@ -59,12 +61,12 @@ public void testTypeMismatch(FunctionDescriptor desc, String expectedExceptionMe public static Object[][] types() { return new Object[][]{ { - FunctionDescriptor.of(MemoryLayout.paddingLayout(64)), - "Unsupported layout: x64" + FunctionDescriptor.of(MemoryLayout.paddingLayout(64)), + "Unsupported layout: x64" }, { - FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(64)), - "Unsupported layout: x64" + FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(64)), + "Unsupported layout: x64" }, { FunctionDescriptor.of(MemoryLayout.sequenceLayout(2, C_INT)), @@ -74,6 +76,42 @@ public static Object[][] types() { FunctionDescriptor.ofVoid(MemoryLayout.sequenceLayout(2, C_INT)), "Unsupported layout: [2:i32]" }, + { + FunctionDescriptor.ofVoid(C_INT.withBitAlignment(16)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(C_POINTER.withBitAlignment(16)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(32)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + C_CHAR.withName("x").withBitAlignment(8), + C_SHORT.withName("y").withBitAlignment(8), + C_INT.withName("z").withBitAlignment(8) + ).withBitAlignment(8)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + MemoryLayout.structLayout( + C_CHAR.withName("x").withBitAlignment(8), + C_SHORT.withName("y").withBitAlignment(8), + C_INT.withName("z").withBitAlignment(8) + ))), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + MemoryLayout.sequenceLayout( + C_INT.withBitAlignment(8) + ))), + "Layout bit alignment must be natural alignment" + }, }; } diff --git a/test/jdk/java/foreign/TestIntrinsics.java b/test/jdk/java/foreign/TestIntrinsics.java index 60ed3faf757..38c742015bb 100644 --- a/test/jdk/java/foreign/TestIntrinsics.java +++ b/test/jdk/java/foreign/TestIntrinsics.java @@ -32,18 +32,18 @@ * TestIntrinsics */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; import java.util.ArrayList; 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; @@ -84,8 +84,7 @@ interface AddIdentity { } AddIdentity addIdentity = (name, carrier, layout, arg) -> { - Addressable ma = findNativeOrThrow(name); - MethodType mt = methodType(carrier, carrier); + MemorySegment ma = findNativeOrThrow(name); FunctionDescriptor fd = FunctionDescriptor.of(layout, layout); tests.add(abi.downcallHandle(ma, fd), arg, arg); @@ -93,8 +92,7 @@ interface AddIdentity { }; { // empty - Addressable ma = findNativeOrThrow("empty"); - MethodType mt = methodType(void.class); + MemorySegment ma = findNativeOrThrow("empty"); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); tests.add(abi.downcallHandle(ma, fd), null); } @@ -108,21 +106,18 @@ interface AddIdentity { addIdentity.add("identity_double", double.class, C_DOUBLE, 10D); { // identity_va - Addressable ma = findNativeOrThrow("identity_va"); - MethodType mt = methodType(int.class, int.class, double.class, int.class, float.class, long.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT).asVariadic(C_DOUBLE, C_INT, C_FLOAT, C_LONG_LONG); - tests.add(abi.downcallHandle(ma, fd), 1, 1, 10D, 2, 3F, 4L); + MemorySegment ma = findNativeOrThrow("identity_va"); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, + C_DOUBLE, C_INT, C_FLOAT, C_LONG_LONG); + tests.add(abi.downcallHandle(ma, fd, firstVariadicArg(1)), 1, 1, 10D, 2, 3F, 4L); } { // high_arity - MethodType baseMT = methodType(void.class, int.class, double.class, long.class, float.class, byte.class, - short.class, char.class); FunctionDescriptor baseFD = FunctionDescriptor.ofVoid(C_INT, C_DOUBLE, C_LONG_LONG, C_FLOAT, C_CHAR, C_SHORT, JAVA_CHAR); Object[] args = {1, 10D, 2L, 3F, (byte) 0, (short) 13, 'a'}; for (int i = 0; i < args.length; i++) { - Addressable ma = findNativeOrThrow("invoke_high_arity" + i); - MethodType mt = baseMT.changeReturnType(baseMT.parameterType(i)); + MemorySegment ma = findNativeOrThrow("invoke_high_arity" + i); FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i)); Object expected = args[i]; tests.add(abi.downcallHandle(ma, fd), expected, args); diff --git a/test/jdk/java/foreign/TestLargeSegmentCopy.java b/test/jdk/java/foreign/TestLargeSegmentCopy.java new file mode 100644 index 00000000000..f75c2e75ca9 --- /dev/null +++ b/test/jdk/java/foreign/TestLargeSegmentCopy.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @requires sun.arch.data.model == "64" + * @bug 8292851 + * @run testng/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; + +public class TestLargeSegmentCopy { + + @Test + public void testLargeSegmentCopy() { + // Make sure the byte size is bigger than Integer.MAX_VALUE + final int longArrayLength = Integer.MAX_VALUE / Long.BYTES + 100; + final long[] array = new long[longArrayLength]; + + try (var arena = Arena.openConfined()) { + var segment = MemorySegment.allocateNative((long) longArrayLength * Long.BYTES, Long.SIZE, arena.scope()); + // Should not throw an exception or error + MemorySegment.copy(segment, JAVA_LONG, 0, array, 0, longArrayLength); + // Should not throw an exception or error + MemorySegment.copy(array,0, segment, JAVA_LONG, 0, longArrayLength); + } + + } + +} diff --git a/test/jdk/java/foreign/TestLayoutEquality.java b/test/jdk/java/foreign/TestLayoutEquality.java index 66c8a8e3fc8..e07638e5078 100644 --- a/test/jdk/java/foreign/TestLayoutEquality.java +++ b/test/jdk/java/foreign/TestLayoutEquality.java @@ -29,7 +29,7 @@ * @run testng TestLayoutEquality */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; import java.lang.foreign.ValueLayout; import jdk.internal.foreign.PlatformLayouts; import org.testng.annotations.DataProvider; @@ -39,24 +39,17 @@ import java.util.ArrayList; import java.util.List; -import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -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.*; public class TestLayoutEquality { @Test(dataProvider = "layoutConstants") public void testReconstructedEquality(ValueLayout layout) { - ValueLayout newLayout = valueLayoutForCarrier(layout.carrier()); + ValueLayout newLayout = MemoryLayout.valueLayout(layout.carrier(), layout.order()); newLayout = newLayout.withBitAlignment(layout.bitAlignment()); - newLayout = newLayout.withOrder(layout.order()); + if (layout instanceof ValueLayout.OfAddress addressLayout && addressLayout.isUnbounded()) { + newLayout = ((ValueLayout.OfAddress)newLayout).asUnbounded(); + } // properties should be equal assertEquals(newLayout.bitSize(), layout.bitSize()); @@ -84,28 +77,4 @@ private static void addLayoutConstants(List testValues, Class cl testValues.add((ValueLayout) f.get(null)); } } - - static ValueLayout valueLayoutForCarrier(Class carrier) { - if (carrier == boolean.class) { - return JAVA_BOOLEAN; - } else if (carrier == char.class) { - return JAVA_CHAR; - } else if (carrier == byte.class) { - return JAVA_BYTE; - } else if (carrier == short.class) { - return JAVA_SHORT; - } else if (carrier == int.class) { - return JAVA_INT; - } else if (carrier == long.class) { - return JAVA_LONG; - } else if (carrier == float.class) { - return JAVA_FLOAT; - } else if (carrier == double.class) { - return JAVA_DOUBLE; - } else if (carrier == MemoryAddress.class) { - return ADDRESS; - } else { - throw new UnsupportedOperationException(); - } - } } diff --git a/test/jdk/java/foreign/TestLayoutPaths.java b/test/jdk/java/foreign/TestLayoutPaths.java index d3daa3ec3ed..59663af8200 100644 --- a/test/jdk/java/foreign/TestLayoutPaths.java +++ b/test/jdk/java/foreign/TestLayoutPaths.java @@ -28,11 +28,11 @@ * @run testng TestLayoutPaths */ +import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; @@ -433,10 +433,10 @@ public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, lon MethodHandle sliceHandle = layout.sliceHandle(pathElements); sliceHandle = sliceHandle.asSpreader(long[].class, indexes.length); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, indexes); - assertEquals(slice.address().toRawLongValue() - segment.address().toRawLongValue(), expectedBitOffset / 8); + assertEquals(slice.address() - segment.address(), expectedBitOffset / 8); assertEquals(slice.byteSize(), selected.byteSize()); } } @@ -468,8 +468,8 @@ public void testSliceHandleUOEInvalidOffsetLate() throws Throwable { return; } - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); try { sliceHandle.invokeExact(segment, 1); // should work diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index 843c88d5e36..e09eaab508a 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -52,8 +52,8 @@ public void testBadLayoutAlignment(MemoryLayout layout, long alignment) { @Test public void testIndexedSequencePath() { MemoryLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement()); // init segment for (int i = 0 ; i < 10 ; i++) { @@ -138,10 +138,15 @@ public void testSequenceBadCount() { @Test(dataProvider = "basicLayouts") public void testSequenceInferredCount(MemoryLayout layout) { - assertEquals(MemoryLayout.sequenceLayout(-1, layout), + assertEquals(MemoryLayout.sequenceLayout(layout), MemoryLayout.sequenceLayout(Long.MAX_VALUE / layout.bitSize(), layout)); } + public void testSequenceNegativeElementCount() { + assertThrows(IllegalArgumentException.class, // negative + () -> MemoryLayout.sequenceLayout(-1, JAVA_SHORT)); + } + @Test public void testSequenceOverflow() { assertThrows(IllegalArgumentException.class, // negative @@ -163,7 +168,7 @@ public void testStructOverflow() { @Test(dataProvider = "layoutKinds") public void testPadding(LayoutKind kind) { - assertEquals(kind == LayoutKind.PADDING, kind.layout.isPadding()); + assertEquals(kind == LayoutKind.PADDING, kind.layout instanceof PaddingLayout); } @Test(dataProvider="layoutsAndAlignments") diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java new file mode 100644 index 00000000000..121e986adb7 --- /dev/null +++ b/test/jdk/java/foreign/TestLinker.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" + * @run testng TestLinker + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.invoke.MethodHandle; + +import static org.testng.Assert.assertNotSame; + +public class TestLinker extends NativeTestHelper { + + @Test + public void testLinkerOptionsCache() { + Linker linker = Linker.nativeLinker(); + FunctionDescriptor descriptor = FunctionDescriptor.ofVoid(C_INT, C_INT); + MethodHandle mh1 = linker.downcallHandle(descriptor); + MethodHandle mh2 = linker.downcallHandle(descriptor, Linker.Option.firstVariadicArg(1)); + // assert that these are 2 distinct link request. No caching allowed + assertNotSame(mh1, mh2); + } + + @DataProvider + public static Object[][] invalidIndexCases() { + return new Object[][]{ + { -1, }, + { 42, }, + }; + } + + @Test(dataProvider = "invalidIndexCases", + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*not in bounds for descriptor.*") + public void testInvalidOption(int invalidIndex) { + Linker.Option option = Linker.Option.firstVariadicArg(invalidIndex); + FunctionDescriptor desc = FunctionDescriptor.ofVoid(); + Linker.nativeLinker().downcallHandle(desc, option); // throws + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Unknown name.*") + public void testInvalidPreservedValueName() { + Linker.Option.captureCallState("foo"); // throws + } + +} diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index 1fa39a40fd8..7028635b682 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -30,12 +30,11 @@ * @run testng/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.Arena; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; @@ -92,8 +91,8 @@ public void testPaddedArrayAccessByIndexSeq(Function viewFactory, MemoryLayout layout, VarHandle handle, Checker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(layout, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(layout, arena.scope())); boolean isRO = segment.isReadOnly(); try { checker.check(handle, segment); @@ -124,8 +123,8 @@ private void testAccessInternal(Function viewFacto private void testArrayAccessInternal(Function viewFactory, SequenceLayout seq, VarHandle handle, ArrayChecker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, arena.scope())); boolean isRO = segment.isReadOnly(); try { for (int i = 0; i < seq.elementCount(); i++) { @@ -193,8 +192,8 @@ public void testPaddedMatrixAccessByIndexSeq(Function viewFactory, SequenceLayout seq, VarHandle handle, MatrixChecker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, arena.scope())); boolean isRO = segment.isReadOnly(); try { for (int i = 0; i < seq.elementCount(); i++) { @@ -465,8 +464,8 @@ interface MatrixChecker { }; MatrixChecker ADDR = (handle, segment, r, c) -> { - handle.set(segment, r, c, MemoryAddress.ofLong(r + c)); - assertEquals(MemoryAddress.ofLong(r + c), (MemoryAddress)handle.get(segment, r, c)); + handle.set(segment, r, c, MemorySegment.ofAddress(r + c)); + assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, r, c)); }; MatrixChecker FLOAT = (handle, segment, r, c) -> { diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index c75aeb45978..e80c170ca65 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -27,9 +27,9 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -80,8 +80,8 @@ interface BufferSetter { } void test() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(128, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(128, arena.scope());; ByteBuffer buffer = segment.asByteBuffer(); T t = transform.apply(segment); segmentSetter.set(t, layout, 8, value); @@ -93,8 +93,8 @@ void test() { @SuppressWarnings("unchecked") void testHyperAligned() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(64, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(64, arena.scope());; T t = transform.apply(segment); L alignedLayout = (L)layout.withBitAlignment(layout.byteSize() * 8 * 2); try { @@ -117,12 +117,6 @@ static Accessor ofSegment(L layo BufferGetter bufferGetter, BufferSetter bufferSetter) { return new Accessor<>(Function.identity(), layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); } - - static Accessor ofAddress(L layout, X value, - SegmentGetter segmentGetter, SegmentSetter segmentSetter, - BufferGetter bufferGetter, BufferSetter bufferSetter) { - return new Accessor<>(MemorySegment::address, layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); - } } @Test(dataProvider = "segmentAccessors") @@ -130,11 +124,6 @@ public void testSegmentAccess(String testName, Accessor accessor) { accessor.test(); } - @Test(dataProvider = "addressAccessors") - public void testAddressAccess(String testName, Accessor accessor) { - accessor.test(); - } - @Test(dataProvider = "segmentAccessors") public void testSegmentAccessHyper(String testName, Accessor accessor) { if (testName.contains("index")) { @@ -144,13 +133,20 @@ public void testSegmentAccessHyper(String testName, Accessor accessor) } } - @Test(dataProvider = "addressAccessors") - public void testAddressAccessHyper(String testName, Accessor accessor) { - if (testName.contains("index")) { - accessor.testHyperAligned(); - } else { - throw new SkipException("Skipping"); - } + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + public void badHeapSegmentSet() { + MemorySegment targetSegment = MemorySegment.allocateNative(ValueLayout.ADDRESS.byteSize(), SegmentScope.auto()); + MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); + targetSegment.set(ValueLayout.ADDRESS, 0, segment); // should throw + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + public void badHeapSegmentSetAtIndex() { + MemorySegment targetSegment = MemorySegment.allocateNative(ValueLayout.ADDRESS.byteSize(), SegmentScope.auto()); + MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); + targetSegment.setAtIndex(ValueLayout.ADDRESS, 0, segment); // should throw } static final ByteOrder NE = ByteOrder.nativeOrder(); @@ -187,20 +183,20 @@ static Object[][] segmentAccessors() { MemorySegment::get, MemorySegment::set, (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) }, - { "address", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + { "address", Accessor.ofSegment(ValueLayout.ADDRESS, MemorySegment.ofAddress(42), MemorySegment::get, MemorySegment::set, (bb, pos) -> { ByteBuffer nb = bb.order(NE); long addr = ValueLayout.ADDRESS.byteSize() == 8 ? nb.getLong(pos) : nb.getInt(pos); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, pos, v) -> { ByteBuffer nb = bb.order(NE); if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos, v.toRawLongValue()); + nb.putLong(pos, v.address()); } else { - nb.putInt(pos, (int)v.toRawLongValue()); + nb.putInt(pos, (int)v.address()); } }) }, @@ -225,112 +221,23 @@ static Object[][] segmentAccessors() { MemorySegment::getAtIndex, MemorySegment::setAtIndex, (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) }, - { "address/index", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + { "address/index", Accessor.ofSegment(ValueLayout.ADDRESS, MemorySegment.ofAddress(42), MemorySegment::getAtIndex, MemorySegment::setAtIndex, (bb, pos) -> { ByteBuffer nb = bb.order(NE); long addr = ValueLayout.ADDRESS.byteSize() == 8 ? nb.getLong(pos * 8) : nb.getInt(pos * 4); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, pos, v) -> { ByteBuffer nb = bb.order(NE); if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos * 8, v.toRawLongValue()); + nb.putLong(pos * 8, v.address()); } else { - nb.putInt(pos * 4, (int)v.toRawLongValue()); + nb.putInt(pos * 4, (int)v.address()); } }) }, }; } - - @DataProvider(name = "addressAccessors") - static Object[][] addressAccessors() { - return new Object[][]{ - - {"byte", Accessor.ofAddress(ValueLayout.JAVA_BYTE, (byte) 42, - MemoryAddress::get, MemoryAddress::set, - ByteBuffer::get, ByteBuffer::put) - }, - {"bool", Accessor.ofAddress(ValueLayout.JAVA_BOOLEAN, false, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.get(pos) != 0, (bb, pos, v) -> bb.put(pos, v ? (byte)1 : (byte)0)) - }, - {"char", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getChar(pos), (bb, pos, v) -> bb.order(NE).putChar(pos, v)) - }, - {"int", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getInt(pos), (bb, pos, v) -> bb.order(NE).putInt(pos, v)) - }, - {"float", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getFloat(pos), (bb, pos, v) -> bb.order(NE).putFloat(pos, v)) - }, - {"long", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getLong(pos), (bb, pos, v) -> bb.order(NE).putLong(pos, v)) - }, - {"double", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) - }, - { "address", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> { - ByteBuffer nb = bb.order(NE); - long addr = ValueLayout.ADDRESS.byteSize() == 8 ? - nb.getLong(pos) : nb.getInt(pos); - return MemoryAddress.ofLong(addr); - }, - (bb, pos, v) -> { - ByteBuffer nb = bb.order(NE); - if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos, v.toRawLongValue()); - } else { - nb.putInt(pos, (int)v.toRawLongValue()); - } - }) - }, - {"char/index", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getChar(pos * 2), (bb, pos, v) -> bb.order(NE).putChar(pos * 2, v)) - }, - {"int/index", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getInt(pos * 4), (bb, pos, v) -> bb.order(NE).putInt(pos * 4, v)) - }, - {"float/index", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getFloat(pos * 4), (bb, pos, v) -> bb.order(NE).putFloat(pos * 4, v)) - }, - {"long/index", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getLong(pos * 8), (bb, pos, v) -> bb.order(NE).putLong(pos * 8, v)) - }, - {"double/index", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) - }, - { "address/index", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> { - ByteBuffer nb = bb.order(NE); - long addr = ValueLayout.ADDRESS.byteSize() == 8 ? - nb.getLong(pos * 8) : nb.getInt(pos * 4); - return MemoryAddress.ofLong(addr); - }, - (bb, pos, v) -> { - ByteBuffer nb = bb.order(NE); - if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos * 8, v.toRawLongValue()); - } else { - nb.putInt(pos * 4, (int)v.toRawLongValue()); - } - }) - } - }; - } } diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index 225557d18f7..cc92085422b 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -27,11 +27,11 @@ * @run testng TestMemoryAlignment */ +import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; @@ -52,8 +52,8 @@ public void testAlignedAccess(long align) { ValueLayout aligned = layout.withBitAlignment(align); assertEquals(aligned.bitAlignment(), align); //unreasonable alignment here, to make sure access throws VarHandle vh = aligned.varHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(aligned, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(aligned, arena.scope());; vh.set(segment, -42); int val = (int)vh.get(segment); assertEquals(val, -42); @@ -70,8 +70,8 @@ public void testUnalignedAccess(long align) { MemoryLayout alignedGroup = MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), aligned); assertEquals(alignedGroup.bitAlignment(), align); VarHandle vh = aligned.varHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(alignedGroup, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(alignedGroup, arena.scope());; vh.set(segment.asSlice(1L), -42); assertEquals(align, 8); //this is the only case where access is aligned } catch (IllegalArgumentException ex) { @@ -97,8 +97,8 @@ public void testUnalignedSequence(long align) { SequenceLayout layout = MemoryLayout.sequenceLayout(5, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withBitAlignment(align)); try { VarHandle vh = layout.varHandle(PathElement.sequenceElement()); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope());; for (long i = 0 ; i < 5 ; i++) { vh.set(segment, i, -42); } @@ -121,8 +121,8 @@ public void testPackedAccess() { 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 (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(g, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(g, arena.scope());; vh_c.set(segment, Byte.MIN_VALUE); assertEquals(vh_c.get(segment), Byte.MIN_VALUE); vh_s.set(segment, Short.MIN_VALUE); diff --git a/test/jdk/java/foreign/TestMemoryDereference.java b/test/jdk/java/foreign/TestMemoryDereference.java index d6d5af5f949..13dd26ce749 100644 --- a/test/jdk/java/foreign/TestMemoryDereference.java +++ b/test/jdk/java/foreign/TestMemoryDereference.java @@ -27,7 +27,6 @@ * @run testng TestMemoryDereference */ -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import java.nio.ByteBuffer; @@ -36,14 +35,7 @@ import java.lang.foreign.ValueLayout; import org.testng.annotations.*; -import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static java.lang.foreign.ValueLayout.*; import static org.testng.Assert.*; public class TestMemoryDereference { @@ -98,14 +90,6 @@ Accessor of(Z value, } } - // unaligned constants - public final static ValueLayout.OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8); - public final static ValueLayout.OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8); - public final static ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - public final static ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - public final static ValueLayout.OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8); - public final static ValueLayout.OfAddress ADDRESS_UNALIGNED = ADDRESS.withBitAlignment(8); - @Test(dataProvider = "accessors") public void testMemoryAccess(String testName, Accessor accessor) { accessor.test(); @@ -204,20 +188,20 @@ static Object[][] accessors() { (s, x) -> s.set(JAVA_DOUBLE_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN), 8, x), (bb) -> bb.order(BE).getDouble(8), (bb, v) -> bb.order(BE).putDouble(8, v)) }, - { "address/offset", new Accessor<>(MemoryAddress.ofLong(42), + { "address/offset", new Accessor<>(MemorySegment.ofAddress(42), s -> s.get(ADDRESS_UNALIGNED, 8), (s, x) -> s.set(ADDRESS_UNALIGNED, 8, x), (bb) -> { ByteBuffer nb = bb.order(NE); long addr = ADDRESS_UNALIGNED.byteSize() == 8 ? nb.getLong(8) : nb.getInt(8); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, v) -> { ByteBuffer nb = bb.order(NE); if (ADDRESS_UNALIGNED.byteSize() == 8) { - nb.putLong(8, v.toRawLongValue()); + nb.putLong(8, v.address()); } else { - nb.putInt(8, (int)v.toRawLongValue()); + nb.putInt(8, (int)v.address()); } }) }, diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java index ff206255cc4..6501978f725 100644 --- a/test/jdk/java/foreign/TestMemorySession.java +++ b/test/jdk/java/foreign/TestMemorySession.java @@ -28,13 +28,11 @@ * @run testng/othervm TestMemorySession */ -import java.lang.ref.Cleaner; +import java.lang.foreign.Arena; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.ref.CleanerFactory; - import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -43,57 +41,39 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import java.util.function.Supplier; -import java.util.function.UnaryOperator; import java.util.stream.IntStream; public class TestMemorySession { final static int N_THREADS = 100; - @Test(dataProvider = "cleaners") - public void testConfined(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test + public void testConfined() { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); - MemorySession session = cleaner != null ? - MemorySession.openConfined(cleaner) : - MemorySession.openConfined(); - session = sessionFunc.apply(session); + Arena arena = Arena.openConfined(); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; - session.addCloseAction(() -> acc.addAndGet(delta)); + addCloseAction(arena.scope(), () -> acc.addAndGet(delta)); } assertEquals(acc.get(), 0); - if (cleaner == null) { - session.close(); - assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); - } else { - session = null; - int expected = IntStream.range(0, N_THREADS).sum(); - while (acc.get() != expected) { - kickGC(); - } - } + arena.close(); + assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } - @Test(dataProvider = "cleaners") - public void testSharedSingleThread(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test(dataProvider = "sharedSessions") + public void testSharedSingleThread(SessionSupplier sessionSupplier) { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); - MemorySession session = cleaner != null ? - MemorySession.openShared(cleaner) : - MemorySession.openShared(); - session = sessionFunc.apply(session); + SegmentScope session = sessionSupplier.get(); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; - session.addCloseAction(() -> acc.addAndGet(delta)); + addCloseAction(session, () -> acc.addAndGet(delta)); } assertEquals(acc.get(), 0); - if (cleaner == null) { - session.close(); + if (!SessionSupplier.isImplicit(session)) { + SessionSupplier.close(session); assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } else { session = null; @@ -104,21 +84,17 @@ public void testSharedSingleThread(Supplier cleanerSupplier, UnaryOpera } } - @Test(dataProvider = "cleaners") - public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test(dataProvider = "sharedSessions") + public void testSharedMultiThread(SessionSupplier sessionSupplier) { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); List threads = new ArrayList<>(); - MemorySession session = cleaner != null ? - MemorySession.openShared(cleaner) : - MemorySession.openShared(); - session = sessionFunc.apply(session); - AtomicReference sessionRef = new AtomicReference<>(session); + SegmentScope session = sessionSupplier.get(); + AtomicReference sessionRef = new AtomicReference<>(session); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; Thread thread = new Thread(() -> { try { - sessionRef.get().addCloseAction(() -> { + addCloseAction(sessionRef.get(), () -> { acc.addAndGet(delta); }); } catch (IllegalStateException ex) { @@ -133,10 +109,10 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat // if no cleaner, close - not all segments might have been added to the session! // if cleaner, don't unset the session - after all, the session is kept alive by threads - if (cleaner == null) { + if (!SessionSupplier.isImplicit(session)) { while (true) { try { - session.close(); + SessionSupplier.close(session); break; } catch (IllegalStateException ise) { // session is acquired (by add) - wait some more @@ -152,7 +128,7 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat } }); - if (cleaner == null) { + if (!SessionSupplier.isImplicit(session)) { assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } else { session = null; @@ -166,22 +142,22 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat @Test public void testLockSingleThread() { - MemorySession session = MemorySession.openConfined(); - List handles = new ArrayList<>(); + Arena arena = Arena.openConfined(); + List handles = new ArrayList<>(); for (int i = 0 ; i < N_THREADS ; i++) { - MemorySession handle = MemorySession.openConfined(); - keepAlive(handle, session); + Arena handle = Arena.openConfined(); + keepAlive(handle.scope(), arena.scope()); handles.add(handle); } while (true) { try { - session.close(); + arena.close(); assertEquals(handles.size(), 0); break; } catch (IllegalStateException ex) { assertTrue(handles.size() > 0); - MemorySession handle = handles.remove(0); + Arena handle = handles.remove(0); handle.close(); } } @@ -189,16 +165,15 @@ public void testLockSingleThread() { @Test public void testLockSharedMultiThread() { - MemorySession session = MemorySession.openShared(); + Arena arena = Arena.openShared(); AtomicInteger lockCount = new AtomicInteger(); for (int i = 0 ; i < N_THREADS ; i++) { new Thread(() -> { - try (MemorySession handle = MemorySession.openConfined()) { - keepAlive(handle, session); + try (Arena handle = Arena.openConfined()) { + keepAlive(handle.scope(), arena.scope()); lockCount.incrementAndGet(); waitSomeTime(); lockCount.decrementAndGet(); - handle.close(); } catch (IllegalStateException ex) { // might be already closed - do nothing } @@ -207,7 +182,7 @@ public void testLockSharedMultiThread() { while (true) { try { - session.close(); + arena.close(); assertEquals(lockCount.get(), 0); break; } catch (IllegalStateException ex) { @@ -218,19 +193,19 @@ public void testLockSharedMultiThread() { @Test public void testCloseEmptyConfinedSession() { - MemorySession.openConfined().close(); + Arena.openConfined().close(); } @Test public void testCloseEmptySharedSession() { - MemorySession.openShared().close(); + Arena.openShared().close(); } @Test public void testCloseConfinedLock() { - MemorySession session = MemorySession.openConfined(); - MemorySession handle = MemorySession.openConfined(); - keepAlive(handle, session); + Arena arena = Arena.openConfined(); + Arena handle = Arena.openConfined(); + keepAlive(handle.scope(), arena.scope()); AtomicReference failure = new AtomicReference<>(); Thread t = new Thread(() -> { try { @@ -249,34 +224,33 @@ public void testCloseConfinedLock() { } } - @Test(dataProvider = "sessions") - public void testSessionAcquires(Supplier sessionFactory) { - MemorySession session = sessionFactory.get(); + @Test(dataProvider = "allSessions") + public void testSessionAcquires(SessionSupplier sessionSupplier) { + SegmentScope session = sessionSupplier.get(); acquireRecursive(session, 5); - if (session.isCloseable()) { - session.close(); - } + if (!SessionSupplier.isImplicit(session)) + SessionSupplier.close(session); } - private void acquireRecursive(MemorySession session, int acquireCount) { - try (MemorySession handle = MemorySession.openConfined()) { - keepAlive(handle, session); + private void acquireRecursive(SegmentScope session, int acquireCount) { + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), session); if (acquireCount > 0) { // recursive acquire acquireRecursive(session, acquireCount - 1); } - if (session.isCloseable()) { - assertThrows(IllegalStateException.class, session::close); + if (!SessionSupplier.isImplicit(session)) { + assertThrows(IllegalStateException.class, () -> SessionSupplier.close(session)); } } } @Test public void testConfinedSessionWithImplicitDependency() { - MemorySession root = MemorySession.openConfined(); + Arena root = Arena.openConfined(); // Create many implicit sessions which depend on 'root', and let them become unreachable. for (int i = 0; i < N_THREADS; i++) { - keepAlive(MemorySession.openConfined(Cleaner.create()), root); + keepAlive(SegmentScope.auto(), root.scope()); } // Now let's keep trying to close 'root' until we succeed. This is trickier than it seems: cleanup action // might be called from another thread (the Cleaner thread), so that the confined session lock count is updated racily. @@ -288,8 +262,8 @@ public void testConfinedSessionWithImplicitDependency() { } catch (IllegalStateException ex) { kickGC(); for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread - try (MemorySession session = MemorySession.openConfined()) { - keepAlive(session, root); + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), root.scope()); // dummy } } @@ -300,19 +274,19 @@ public void testConfinedSessionWithImplicitDependency() { @Test public void testConfinedSessionWithSharedDependency() { - MemorySession root = MemorySession.openConfined(); + Arena root = Arena.openConfined(); List threads = new ArrayList<>(); // Create many implicit sessions which depend on 'root', and let them become unreachable. for (int i = 0; i < N_THREADS; i++) { - MemorySession session = MemorySession.openShared(); // create session inside same thread! - keepAlive(session, root); - Thread t = new Thread(session::close); // close from another thread! + Arena arena = Arena.openShared(); // create session inside same thread! + keepAlive(arena.scope(), root.scope()); + Thread t = new Thread(arena::close); // close from another thread! threads.add(t); t.start(); } for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread - try (MemorySession session = MemorySession.openConfined()) { - keepAlive(session, root); + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), root.scope()); // dummy } } @@ -345,33 +319,57 @@ private void kickGC() { } @DataProvider - static Object[][] cleaners() { + static Object[][] drops() { return new Object[][] { - { (Supplier)() -> null, UnaryOperator.identity() }, - { (Supplier)Cleaner::create, UnaryOperator.identity() }, - { (Supplier)CleanerFactory::cleaner, UnaryOperator.identity() }, - { (Supplier)Cleaner::create, (UnaryOperator)MemorySession::asNonCloseable }, - { (Supplier)CleanerFactory::cleaner, (UnaryOperator)MemorySession::asNonCloseable } + { (Supplier) Arena::openConfined}, + { (Supplier) Arena::openShared}, }; } - @DataProvider - static Object[][] sessions() { + private void keepAlive(SegmentScope child, SegmentScope parent) { + MemorySessionImpl parentImpl = (MemorySessionImpl) parent; + parentImpl.acquire0(); + addCloseAction(child, parentImpl::release0); + } + + private void addCloseAction(SegmentScope session, Runnable action) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + sessionImpl.addCloseAction(action); + } + + interface SessionSupplier extends Supplier { + + static void close(SegmentScope session) { + ((MemorySessionImpl)session).close(); + } + + static boolean isImplicit(SegmentScope session) { + return !((MemorySessionImpl)session).isCloseable(); + } + + static SessionSupplier ofImplicit() { + return SegmentScope::auto; + } + + static SessionSupplier ofArena(Supplier arenaSupplier) { + return () -> arenaSupplier.get().scope(); + } + } + + @DataProvider(name = "sharedSessions") + static Object[][] sharedSessions() { return new Object[][] { - { (Supplier) MemorySession::openConfined}, - { (Supplier) MemorySession::openShared}, - { (Supplier) MemorySession::openImplicit}, - { (Supplier) MemorySession::global}, - { (Supplier) () -> MemorySession.openConfined().asNonCloseable() }, - { (Supplier) () -> MemorySession.openShared().asNonCloseable() }, - { (Supplier) () -> MemorySession.openImplicit().asNonCloseable() }, - { (Supplier) () -> MemorySession.global().asNonCloseable()}, + { SessionSupplier.ofArena(Arena::openShared) }, + { SessionSupplier.ofImplicit() }, }; } - private void keepAlive(MemorySession child, MemorySession parent) { - MemorySessionImpl parentImpl = MemorySessionImpl.toSessionImpl(parent); - parentImpl.acquire0(); - child.addCloseAction(parentImpl::release0); + @DataProvider(name = "allSessions") + static Object[][] allSessions() { + return new Object[][] { + { SessionSupplier.ofArena(Arena::openConfined) }, + { SessionSupplier.ofArena(Arena::openShared) }, + { SessionSupplier.ofImplicit() }, + }; } } diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index acdf2046d31..e7a381b9ce5 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -27,8 +27,8 @@ * @run testng TestMismatch */ -import java.lang.foreign.MemorySession; -import java.lang.invoke.VarHandle; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -36,6 +36,7 @@ import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.util.function.IntFunction; +import java.util.stream.Stream; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -45,16 +46,44 @@ public class TestMismatch { - final static VarHandle BYTE_HANDLE = ValueLayout.JAVA_BYTE.varHandle(); - // stores a increasing sequence of values into the memory of the given segment static MemorySegment initializeSegment(MemorySegment segment) { for (int i = 0 ; i < segment.byteSize() ; i++) { - BYTE_HANDLE.set(segment.asSlice(i), (byte)i); + segment.set(ValueLayout.JAVA_BYTE, i, (byte)i); } return segment; } + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcFromOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, -1, 0, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstFromOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, -1, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcToOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, -1, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstToOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, 0, -1); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcLength(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 3, 2, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstLength(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, 3, 2); + } + @Test(dataProvider = "slices") public void testSameValues(MemorySegment ss1, MemorySegment ss2) { out.format("testSameValues s1:%s, s2:%s\n", ss1, ss2); @@ -74,6 +103,26 @@ public void testSameValues(MemorySegment ss1, MemorySegment ss2) { } } + @Test(dataProvider = "slicesStatic") + public void testSameValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { + out.format("testSameValuesStatic s1:%s, s2:%s\n", ss1, ss2); + MemorySegment s1 = initializeSegment(ss1.toSlice()); + MemorySegment s2 = initializeSegment(ss2.toSlice()); + + for (long i = ss2.offset ; i < ss2.size ; i++) { + 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); + } + 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); + } + } + @Test(dataProvider = "slices") public void testDifferentValues(MemorySegment s1, MemorySegment s2) { out.format("testDifferentValues s1:%s, s2:%s\n", s1, s2); @@ -82,7 +131,7 @@ public void testDifferentValues(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= 0; i--) { long expectedMismatchOffset = i; - BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF); + s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); if (s1.byteSize() == s2.byteSize()) { assertEquals(s1.mismatch(s2), expectedMismatchOffset); @@ -99,12 +148,32 @@ public void testDifferentValues(MemorySegment s1, MemorySegment s2) { } } + @Test(dataProvider = "slicesStatic") + public void testDifferentValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { + out.format("testDifferentValues s1:%s, s2:%s\n", ss1, ss2); + + for (long i = ss2.size - 1 ; i >= 0; i--) { + if (i >= ss1.size) continue; + initializeSegment(ss1.toSlice()); + initializeSegment(ss2.toSlice()); + long expectedMismatchOffset = i; + 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); + } + 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); + } + } + } + @Test public void testEmpty() { var s1 = MemorySegment.ofArray(new byte[0]); assertEquals(s1.mismatch(s1), -1); - try (MemorySession session = MemorySession.openConfined()) { - var nativeSegment = MemorySegment.allocateNative(4, 4, session); + try (Arena arena = Arena.openConfined()) { + var nativeSegment = MemorySegment.allocateNative(4, 4, arena.scope());; var s2 = nativeSegment.asSlice(0, 0); assertEquals(s1.mismatch(s2), -1); assertEquals(s2.mismatch(s1), -1); @@ -115,9 +184,9 @@ public void testEmpty() { public void testLarge() { // skip if not on 64 bits if (ValueLayout.ADDRESS.byteSize() > 32) { - try (MemorySession session = MemorySession.openConfined()) { - var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, session); - var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, session); + try (Arena arena = Arena.openConfined()) { + var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, arena.scope());; + var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, arena.scope());; assertEquals(s1.mismatch(s1), -1); assertEquals(s1.mismatch(s2), -1); assertEquals(s2.mismatch(s1), -1); @@ -133,15 +202,20 @@ private void testLargeAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { 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); + // 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); } } private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { - BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF); + s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); long expectedMismatchOffset = i; assertEquals(s1.mismatch(s2), expectedMismatchOffset); assertEquals(s2.mismatch(s1), expectedMismatchOffset); @@ -154,9 +228,9 @@ private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment @Test public void testClosed() { MemorySegment s1, s2; - try (MemorySession session = MemorySession.openConfined()) { - s1 = MemorySegment.allocateNative(4, 1, session); - s2 = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + s1 = MemorySegment.allocateNative(4, 1, arena.scope());; + s2 = MemorySegment.allocateNative(4, 1, arena.scope());; } assertThrows(ISE, () -> s1.mismatch(s1)); assertThrows(ISE, () -> s1.mismatch(s2)); @@ -165,8 +239,8 @@ public void testClosed() { @Test public void testThreadAccess() throws Exception { - try (MemorySession session = MemorySession.openConfined()) { - var segment = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + var segment = MemorySegment.allocateNative(4, 1, arena.scope());; { AtomicReference exception = new AtomicReference<>(); Runnable action = () -> { @@ -207,7 +281,7 @@ public void testThreadAccess() throws Exception { } enum SegmentKind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openImplicit())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; @@ -221,30 +295,48 @@ MemorySegment makeSegment(int elems) { } } - @DataProvider(name = "slices") - static Object[][] slices() { + record SliceOffsetAndSize(MemorySegment segment, long offset, long size) { + MemorySegment toSlice() { + return segment.asSlice(offset, size); + } + long endOffset() { + return offset + size; + } + }; + + @DataProvider(name = "slicesStatic") + static Object[][] slicesStatic() { int[] sizes = { 16, 8, 1 }; - List aSlices = new ArrayList<>(); - List bSlices = new ArrayList<>(); - for (List slices : List.of(aSlices, bSlices)) { + List aSliceOffsetAndSizes = new ArrayList<>(); + List bSliceOffsetAndSizes = new ArrayList<>(); + for (List slices : List.of(aSliceOffsetAndSizes, bSliceOffsetAndSizes)) { for (SegmentKind kind : SegmentKind.values()) { MemorySegment segment = kind.makeSegment(16); //compute all slices for (int size : sizes) { for (int index = 0 ; index < 16 ; index += size) { - MemorySegment slice = segment.asSlice(index, size); - slices.add(slice); + slices.add(new SliceOffsetAndSize(segment, index, size)); } } } } - assert aSlices.size() == bSlices.size(); - Object[][] sliceArray = new Object[aSlices.size() * bSlices.size()][]; - for (int i = 0 ; i < aSlices.size() ; i++) { - for (int j = 0 ; j < bSlices.size() ; j++) { - sliceArray[i * aSlices.size() + j] = new Object[] { aSlices.get(i), bSlices.get(j) }; + assert aSliceOffsetAndSizes.size() == bSliceOffsetAndSizes.size(); + Object[][] sliceArray = new Object[aSliceOffsetAndSizes.size() * bSliceOffsetAndSizes.size()][]; + for (int i = 0 ; i < aSliceOffsetAndSizes.size() ; i++) { + for (int j = 0 ; j < bSliceOffsetAndSizes.size() ; j++) { + sliceArray[i * aSliceOffsetAndSizes.size() + j] = new Object[] { aSliceOffsetAndSizes.get(i), bSliceOffsetAndSizes.get(j) }; } } return sliceArray; } + + @DataProvider(name = "slices") + static Object[][] slices() { + Object[][] slicesStatic = slicesStatic(); + return Stream.of(slicesStatic) + .map(arr -> new Object[]{ + ((SliceOffsetAndSize) arr[0]).toSlice(), + ((SliceOffsetAndSize) arr[1]).toSlice() + }).toArray(Object[][]::new); + } } diff --git a/test/jdk/java/foreign/TestNULLAddress.java b/test/jdk/java/foreign/TestNULLAddress.java index 93d9fe7ab6b..803b5d7fed5 100644 --- a/test/jdk/java/foreign/TestNULLAddress.java +++ b/test/jdk/java/foreign/TestNULLAddress.java @@ -32,20 +32,27 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; +import static org.testng.Assert.*; + public class TestNULLAddress { + static { + System.loadLibrary("Null"); + } + static final Linker LINKER = Linker.nativeLinker(); @Test(expectedExceptions = IllegalArgumentException.class) public void testNULLLinking() { LINKER.downcallHandle( - MemoryAddress.NULL, + MemorySegment.NULL, FunctionDescriptor.ofVoid()); } @@ -53,16 +60,22 @@ public void testNULLLinking() { public void testNULLVirtual() throws Throwable { MethodHandle mh = LINKER.downcallHandle( FunctionDescriptor.ofVoid()); - mh.invokeExact((Addressable)MemoryAddress.NULL); + mh.invokeExact(MemorySegment.NULL); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLgetString() { - MemoryAddress.NULL.getUtf8String(0); + @Test + public void testNULLReturn_unbounded() throws Throwable { + MethodHandle mh = LINKER.downcallHandle(SymbolLookup.loaderLookup().find("get_null").get(), + FunctionDescriptor.of(ValueLayout.ADDRESS.asUnbounded())); + MemorySegment ret = (MemorySegment)mh.invokeExact(); + assertTrue(ret.equals(MemorySegment.NULL)); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLsetString() { - MemoryAddress.NULL.setUtf8String(0, "hello"); + @Test + public void testNULLReturn_plain() throws Throwable { + MethodHandle mh = LINKER.downcallHandle(SymbolLookup.loaderLookup().find("get_null").get(), + FunctionDescriptor.of(ValueLayout.ADDRESS)); + MemorySegment ret = (MemorySegment)mh.invokeExact(); + assertTrue(ret.equals(MemorySegment.NULL)); } } diff --git a/test/jdk/java/foreign/TestNative.java b/test/jdk/java/foreign/TestNative.java index 4f6aa24a3e4..672d6d7db2e 100644 --- a/test/jdk/java/foreign/TestNative.java +++ b/test/jdk/java/foreign/TestNative.java @@ -29,11 +29,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNative */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import org.testng.annotations.DataProvider; @@ -112,7 +112,7 @@ static void checkBytes(MemorySegment base, SequenceLayout lay for (long i = 0 ; i < nelems ; i++) { Object handleValue = handleExtractor.apply(base, i); Object bufferValue = nativeBufferExtractor.apply(z, (int)i); - Object rawValue = nativeRawExtractor.apply(base.address().toRawLongValue(), (int)i); + Object rawValue = nativeRawExtractor.apply(base.address(), (int)i); if (handleValue instanceof Number) { assertEquals(((Number)handleValue).longValue(), i); assertEquals(((Number)bufferValue).longValue(), i); @@ -145,8 +145,8 @@ static void checkBytes(MemorySegment base, SequenceLayout lay @Test(dataProvider="nativeAccessOps") public void testNativeAccess(Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); checker.accept(segment); } @@ -155,8 +155,8 @@ public void testNativeAccess(Consumer checker, Consumer bufferFunction, int elemSize) { int capacity = (int)doubles.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(doubles, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(doubles, arena.scope());; ByteBuffer bb = segment.asByteBuffer(); Buffer buf = bufferFunction.apply(bb); int expected = capacity / elemSize; @@ -167,30 +167,30 @@ public void testNativeCapacity(Function bufferFunction, int @Test public void testDefaultAccessModes() { - MemoryAddress addr = allocateMemory(12); - try (MemorySession session = MemorySession.openConfined()) { - session.addCloseAction(() -> freeMemory(addr)); - MemorySegment mallocSegment = MemorySegment.ofAddress(addr, 12, session); + MemorySegment addr = allocateMemory(12); + try (Arena arena = Arena.openConfined()) { + MemorySegment mallocSegment = MemorySegment.ofAddress(addr.address(), 12, + arena.scope(), () -> freeMemory(addr)); assertFalse(mallocSegment.isReadOnly()); } } @Test public void testMallocSegment() { - MemoryAddress addr = allocateMemory(12); + MemorySegment addr = allocateMemory(12); MemorySegment mallocSegment = null; - try (MemorySession session = MemorySession.openConfined()) { - session.addCloseAction(() -> freeMemory(addr)); - mallocSegment = MemorySegment.ofAddress(addr, 12, session); + try (Arena arena = Arena.openConfined()) { + mallocSegment = MemorySegment.ofAddress(addr.address(), 12, + arena.scope(), () -> freeMemory(addr)); assertEquals(mallocSegment.byteSize(), 12); //free here } - assertTrue(!mallocSegment.session().isAlive()); + assertTrue(!mallocSegment.scope().isAlive()); } @Test public void testAddressAccess() { - MemoryAddress addr = allocateMemory(4); + MemorySegment addr = allocateMemory(4); addr.set(JAVA_INT, 0, 42); assertEquals(addr.get(JAVA_INT, 0), 42); freeMemory(addr); @@ -198,9 +198,9 @@ public void testAddressAccess() { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadResize() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(4, 1, session); - MemorySegment.ofAddress(segment.address(), -1, MemorySession.global()); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(4, 1, arena.scope());; + MemorySegment.ofAddress(segment.address(), -1, SegmentScope.global()); } } diff --git a/test/jdk/java/foreign/TestNulls.java b/test/jdk/java/foreign/TestNulls.java index 3c79d4cff6d..c72b5fefd61 100644 --- a/test/jdk/java/foreign/TestNulls.java +++ b/test/jdk/java/foreign/TestNulls.java @@ -32,12 +32,14 @@ */ 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.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -79,8 +81,8 @@ public class TestNulls { static final Class[] CLASSES = new Class[] { + Arena.class, MemorySegment.class, - MemoryAddress.class, MemoryLayout.class, MemoryLayout.PathElement.class, SequenceLayout.class, @@ -95,19 +97,19 @@ public class TestNulls { ValueLayout.OfDouble.class, ValueLayout.OfAddress.class, GroupLayout.class, - Addressable.class, Linker.class, VaList.class, VaList.Builder.class, FunctionDescriptor.class, SegmentAllocator.class, - MemorySession.class, + SegmentScope.class, SymbolLookup.class }; static final Set EXCLUDE_LIST = Set.of( - "java.lang.foreign.MemorySession/openConfined(java.lang.ref.Cleaner)/0/0", - "java.lang.foreign.MemorySession/openShared(java.lang.ref.Cleaner)/0/0", + "java.lang.foreign.MemorySegment/ofAddress(long,long,java.lang.foreign.SegmentScope,java.lang.Runnable)/3/0", + "java.lang.foreign.MemorySegment.MemorySession/openConfined(java.lang.ref.Cleaner)/0/0", + "java.lang.foreign.MemorySegment.MemorySession/openShared(java.lang.ref.Cleaner)/0/0", "java.lang.foreign.MemoryLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "java.lang.foreign.SequenceLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "java.lang.foreign.ValueLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", @@ -162,8 +164,6 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(Charset.class, Charset.defaultCharset()); addDefaultMapping(Consumer.class, x -> {}); addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); - addDefaultMapping(MemoryAddress.class, MemoryAddress.ofLong(1)); - addDefaultMapping(Addressable.class, MemoryAddress.ofLong(1)); addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(ValueLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(ValueLayout.OfAddress.class, ValueLayout.ADDRESS); @@ -183,7 +183,8 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(Linker.class, Linker.nativeLinker()); addDefaultMapping(VaList.class, VaListHelper.vaList); addDefaultMapping(VaList.Builder.class, VaListHelper.vaListBuilder); - addDefaultMapping(MemorySession.class, MemorySession.openShared()); + addDefaultMapping(Arena.class, Arena.openConfined()); + addDefaultMapping(SegmentScope.class, SegmentScope.auto()); addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); addDefaultMapping(Supplier.class, () -> null); addDefaultMapping(ClassLoader.class, TestNulls.class.getClassLoader()); @@ -198,7 +199,7 @@ static class VaListHelper { vaList = VaList.make(b -> { builderRef.set(b); b.addVarg(JAVA_LONG, 42L); - }, MemorySession.openImplicit()); + }, SegmentScope.auto()); vaListBuilder = builderRef.get(); } } diff --git a/test/jdk/java/foreign/TestOfBufferIssue.java b/test/jdk/java/foreign/TestOfBufferIssue.java new file mode 100644 index 00000000000..df8d62ccf20 --- /dev/null +++ b/test/jdk/java/foreign/TestOfBufferIssue.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, 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. + * + */ + +import org.testng.annotations.*; + +import java.lang.foreign.MemorySegment; +import java.nio.CharBuffer; + +import static org.testng.Assert.*; + +/* + * @test + * @bug 8294621 + * @summary test that StringCharBuffer is not accepted by MemorySegment::ofBuffer + * @enablePreview + * @run testng TestOfBufferIssue + */ + +public class TestOfBufferIssue { + + @Test + public void ensure8294621Fixed() { + try { + final CharBuffer cb = CharBuffer.wrap("Hello"); + MemorySegment src2 = MemorySegment.ofBuffer(cb); + fail("A StringCharBuffer is not allowed as an argument."); + } catch (IllegalArgumentException iae) { + // Ignored. Happy path + } + } + +} diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index fa15e48ce0a..986703a02a5 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -28,13 +28,14 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.VaList; import java.lang.foreign.ValueLayout; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -73,9 +74,9 @@ public class TestScopedOperations { @Test(dataProvider = "scopedOperations") public void testOpAfterClose(String name, ScopedOperation scopedOperation) { - MemorySession session = MemorySession.openConfined(); - Z obj = scopedOperation.apply(session); - session.close(); + Arena arena = Arena.openConfined(); + Z obj = scopedOperation.apply(arena.scope()); + arena.close(); try { scopedOperation.accept(obj); fail(); @@ -86,8 +87,8 @@ public void testOpAfterClose(String name, ScopedOperation scopedOperation @Test(dataProvider = "scopedOperations") public void testOpOutsideConfinement(String name, ScopedOperation scopedOperation) { - try (MemorySession session = MemorySession.openConfined()) { - Z obj = scopedOperation.apply(session); + try (Arena arena = Arena.openConfined()) { + Z obj = scopedOperation.apply(arena.scope()); AtomicReference failed = new AtomicReference<>(); Thread t = new Thread(() -> { try { @@ -110,9 +111,7 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO static { // session operations - ScopedOperation.ofScope(session -> session.addCloseAction(() -> { - }), "MemorySession::addCloseAction"); - ScopedOperation.ofScope(session -> MemorySegment.allocateNative(100, session), "MemorySegment::allocateNative"); + ScopedOperation.ofScope(session -> MemorySegment.allocateNative(100, session), "MemorySession::allocate");; ScopedOperation.ofScope(session -> { try (FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 10L, session); @@ -121,16 +120,13 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO } }, "FileChannel::map"); ScopedOperation.ofScope(session -> VaList.make(b -> b.addVarg(JAVA_INT, 42), session), "VaList::make"); - ScopedOperation.ofScope(session -> VaList.ofAddress(MemoryAddress.ofLong(42), session), "VaList::make"); - ScopedOperation.ofScope(SegmentAllocator::newNativeArena, "SegmentAllocator::arenaAllocator"); + ScopedOperation.ofScope(session -> VaList.ofAddress(42, session), "VaList::make"); // segment operations ScopedOperation.ofSegment(s -> s.toArray(JAVA_BYTE), "MemorySegment::toArray(BYTE)"); - ScopedOperation.ofSegment(MemorySegment::address, "MemorySegment::address"); ScopedOperation.ofSegment(s -> s.copyFrom(s), "MemorySegment::copyFrom"); ScopedOperation.ofSegment(s -> s.mismatch(s), "MemorySegment::mismatch"); ScopedOperation.ofSegment(s -> s.fill((byte) 0), "MemorySegment::fill"); // valist operations - ScopedOperation.ofVaList(VaList::address, "VaList::address"); ScopedOperation.ofVaList(VaList::copy, "VaList::copy"); ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.ADDRESS), "VaList::nextVarg/address"); ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.JAVA_INT), "VaList::nextVarg/int"); @@ -165,13 +161,13 @@ static Object[][] scopedOperations() { return scopedOperations.stream().map(op -> new Object[] { op.name, op }).toArray(Object[][]::new); } - static class ScopedOperation implements Consumer, Function { + static class ScopedOperation implements Consumer, Function { - final Function factory; + final Function factory; final Consumer operation; final String name; - private ScopedOperation(Function factory, Consumer operation, String name) { + private ScopedOperation(Function factory, Consumer operation, String name) { this.factory = factory; this.operation = operation; this.name = name; @@ -183,15 +179,15 @@ public void accept(X obj) { } @Override - public X apply(MemorySession session) { + public X apply(SegmentScope session) { return factory.apply(session); } - static void of(Function factory, Consumer consumer, String name) { + static void of(Function factory, Consumer consumer, String name) { scopedOperations.add(new ScopedOperation<>(factory, consumer, name)); } - static void ofScope(Consumer scopeConsumer, String name) { + static void ofScope(Consumer scopeConsumer, String name) { scopedOperations.add(new ScopedOperation<>(Function.identity(), scopeConsumer, name)); } @@ -228,7 +224,7 @@ enum SegmentFactory { throw new AssertionError(ex); } }), - UNSAFE(session -> MemorySegment.ofAddress(MemoryAddress.NULL, 10, session)); + UNSAFE(session -> MemorySegment.ofAddress(0, 10, session)); static { try { @@ -240,20 +236,19 @@ enum SegmentFactory { } } - final Function segmentFactory; + final Function segmentFactory; - SegmentFactory(Function segmentFactory) { + SegmentFactory(Function segmentFactory) { this.segmentFactory = segmentFactory; } } enum AllocatorFactory { - ARENA_BOUNDED(session -> SegmentAllocator.newNativeArena(1000, session)), - ARENA_UNBOUNDED(SegmentAllocator::newNativeArena); + NATIVE_ALLOCATOR(SegmentAllocator::nativeAllocator); - final Function allocatorFactory; + final Function allocatorFactory; - AllocatorFactory(Function allocatorFactory) { + AllocatorFactory(Function allocatorFactory) { this.allocatorFactory = allocatorFactory; } } diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index a5cca846dc5..94dd265563e 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -32,6 +32,7 @@ import org.testng.annotations.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -46,8 +47,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.IntStream; -import java.util.stream.LongStream; import static org.testng.Assert.*; @@ -69,13 +68,13 @@ public void testAllocation(Z value, AllocationFactory for (L alignedLayout : layouts) { List addressList = new ArrayList<>(); int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment()); - MemorySession[] sessions = { - MemorySession.openConfined(), - MemorySession.openShared() + Arena[] arenas = { + Arena.openConfined(), + Arena.openShared() }; - for (MemorySession session : sessions) { - try (session) { - SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, session); + for (Arena arena : arenas) { + try (arena) { + 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()); @@ -87,16 +86,14 @@ public void testAllocation(Z value, AllocationFactory try { allocationFunction.allocate(allocator, alignedLayout, value); assertFalse(isBound); - } catch (OutOfMemoryError ex) { + } catch (IndexOutOfBoundsException ex) { //failure is expected if bound assertTrue(isBound); } } - if (allocationFactory != AllocationFactory.IMPLICIT_ALLOCATOR) { - // addresses should be invalid now - for (MemorySegment address : addressList) { - assertFalse(address.session().isAlive()); - } + // addresses should be invalid now + for (MemorySegment address : addressList) { + assertFalse(address.scope().isAlive()); } } } @@ -106,40 +103,27 @@ public void testAllocation(Z value, AllocationFactory @Test public void testBigAllocationInUnboundedSession() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + try (Arena arena = Arena.openConfined()) { for (int i = 8 ; i < SIZE_256M ; i *= 8) { + SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1)); MemorySegment address = allocator.allocate(i, i); //check size assertEquals(address.byteSize(), i); //check alignment - assertEquals(address.address().toRawLongValue() % i, 0); + assertEquals(address.address() % i, 0); } } } @Test public void testTooBigForBoundedArena() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(10, session); - assertThrows(OutOfMemoryError.class, () -> allocator.allocate(12)); - allocator.allocate(5); // ok - } - } - - @Test - public void testBiggerThanBlockForBoundedArena() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(4 * 1024 * 2, session); - allocator.allocate(4 * 1024 + 1); // should be ok + try (Arena arena = Arena.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(10)); + assertThrows(IndexOutOfBoundsException.class, () -> allocator.allocate(12)); + allocator.allocate(5); } } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadUnboundedArenaSize() { - SegmentAllocator.newNativeArena( -1, MemorySession.global()); - } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationSize(SegmentAllocator allocator) { allocator.allocate(-1); @@ -167,8 +151,9 @@ public void testBadAllocationArrayNegSize(SegmentAllocator allocator) { @Test(expectedExceptions = OutOfMemoryError.class) public void testBadArenaNullReturn() { - SegmentAllocator segmentAllocator = SegmentAllocator.newNativeArena(MemorySession.openImplicit()); - segmentAllocator.allocate(Long.MAX_VALUE, 2); + try (Arena arena = Arena.openConfined()) { + arena.allocate(Long.MAX_VALUE, 2); + } } @Test @@ -176,7 +161,7 @@ public void testArrayAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { + public MemorySegment allocate(long bytesSize, long byteAlignment) { return null; } @@ -201,8 +186,9 @@ public void testStringAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - return MemorySegment.allocateNative(bytesSize, bytesAlignment, MemorySession.openImplicit()); + + public MemorySegment allocate(long byteSize, long byteAlignment) { + return MemorySegment.allocateNative(byteSize, byteAlignment, SegmentScope.auto()); } @Override @@ -219,13 +205,13 @@ public MemorySegment allocate(long size) { @Test(dataProvider = "arrayAllocations") public void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); - MemorySession[] sessions = { - MemorySession.openConfined(), - MemorySession.openShared() + Arena[] arenas = { + Arena.openConfined(), + Arena.openShared() }; - for (MemorySession session : sessions) { - try (session) { - SegmentAllocator allocator = allocationFactory.allocator(100, session); + for (Arena arena : arenas) { + try (arena) { + SegmentAllocator allocator = allocationFactory.allocator(100, arena); MemorySegment address = allocationFunction.allocate(allocator, layout, arr); Z found = arrayHelper.toArray(address, layout); assertEquals(found, arr); @@ -259,7 +245,7 @@ static Object[][] scalarAllocations() { scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); - scalarAllocations.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); @@ -282,7 +268,7 @@ static Object[][] scalarAllocations() { scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); - scalarAllocations.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); } @@ -350,7 +336,7 @@ interface OfInt extends AllocationFunction { } interface OfFloat extends AllocationFunction { } interface OfLong extends AllocationFunction { } interface OfDouble extends AllocationFunction { } - interface OfAddress extends AllocationFunction { } + interface OfAddress extends AllocationFunction { } interface OfByteArray extends AllocationFunction { } interface OfCharArray extends AllocationFunction { } @@ -362,21 +348,19 @@ interface OfDoubleArray extends AllocationFunction SegmentAllocator.newNativeArena(session)), - NATIVE_ALLOCATOR(false, (size, session) -> session), - IMPLICIT_ALLOCATOR(false, (size, session) -> SegmentAllocator.implicitAllocator()); + SLICING(true, (size, drop) -> SegmentAllocator.slicingAllocator(MemorySegment.allocateNative(size, drop.scope()))), + NATIVE_ALLOCATOR(false, (size, drop) -> SegmentAllocator.nativeAllocator(drop.scope())); private final boolean isBound; - private final BiFunction factory; + private final BiFunction factory; - AllocationFactory(boolean isBound, BiFunction factory) { + AllocationFactory(boolean isBound, BiFunction factory) { this.isBound = isBound; this.factory = factory; } - SegmentAllocator allocator(long size, MemorySession session) { - return factory.apply(size, session); + SegmentAllocator allocator(long size, Arena arena) { + return factory.apply(size, arena); } public boolean isBound() { @@ -492,42 +476,13 @@ public double[] toArray(MemorySegment segment, ValueLayout layout) { return found; } }; - - ToArrayHelper toAddressArray = new ToArrayHelper<>() { - @Override - public MemoryAddress[] array() { - return switch ((int) ValueLayout.ADDRESS.byteSize()) { - case 4 -> wrap(toIntArray.array()); - case 8 -> wrap(toLongArray.array()); - default -> throw new IllegalStateException("Cannot get here"); - }; - } - - @Override - public MemoryAddress[] toArray(MemorySegment segment, ValueLayout layout) { - return switch ((int)layout.byteSize()) { - case 4 -> wrap(toIntArray.toArray(segment, layout)); - case 8 -> wrap(toLongArray.toArray(segment, layout)); - default -> throw new IllegalStateException("Cannot get here"); - }; - } - - private MemoryAddress[] wrap(int[] ints) { - return IntStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new); - } - - private MemoryAddress[] wrap(long[] ints) { - return LongStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new); - } - }; } @DataProvider(name = "allocators") static Object[][] allocators() { return new Object[][] { - { SegmentAllocator.implicitAllocator() }, - { SegmentAllocator.newNativeArena(MemorySession.global()) }, - { SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(10, MemorySession.global())) }, + { SegmentAllocator.nativeAllocator(SegmentScope.global()) }, + { SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(10, SegmentScope.global())) }, }; } } diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index 0a3de9a2476..c82d4e5ded8 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -29,7 +29,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -144,7 +144,7 @@ void check(SegmentSlice slice, int index, int val) { static class SegmentSlice { enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openImplicit())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; diff --git a/test/jdk/java/foreign/TestSegmentOffset.java b/test/jdk/java/foreign/TestSegmentOffset.java index bb4263b66d9..f3adcb67c89 100644 --- a/test/jdk/java/foreign/TestSegmentOffset.java +++ b/test/jdk/java/foreign/TestSegmentOffset.java @@ -28,9 +28,11 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; + +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; import java.util.function.IntFunction; @@ -79,7 +81,7 @@ public void testOffset(SegmentSlice s1, SegmentSlice s2) { static class SegmentSlice { enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openConfined())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; diff --git a/test/jdk/java/foreign/TestSegmentOverlap.java b/test/jdk/java/foreign/TestSegmentOverlap.java index 1c08240dbde..bb0e07da817 100644 --- a/test/jdk/java/foreign/TestSegmentOverlap.java +++ b/test/jdk/java/foreign/TestSegmentOverlap.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.IOException; +import java.lang.foreign.SegmentScope; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; @@ -36,7 +37,7 @@ import java.util.List; import java.util.function.Supplier; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.Test; import org.testng.annotations.DataProvider; import static java.lang.System.out; @@ -61,10 +62,10 @@ public class TestSegmentOverlap { @DataProvider(name = "segmentFactories") public Object[][] segmentFactories() { List> l = List.of( - () -> MemorySegment.allocateNative(16, MemorySession.openConfined()), + () -> MemorySegment.allocateNative(16, SegmentScope.auto()), () -> { try (FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - return fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 16L, MemorySession.openConfined()); + return fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 16L, SegmentScope.auto()); } catch (IOException e) { throw new RuntimeException(e); } @@ -98,10 +99,10 @@ public void testIdentical(Supplier segmentSupplier) { 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().session(), s1.session()); + assertEquals(s1.asOverlappingSlice(s2).get().scope(), s1.scope()); assertEquals(s2.asOverlappingSlice(s1).get().byteSize(), s2.byteSize()); - assertEquals(s2.asOverlappingSlice(s1).get().session(), s2.session()); + assertEquals(s2.asOverlappingSlice(s1).get().scope(), s2.scope()); if (s1.isNative()) { assertEquals(s1.asOverlappingSlice(s2).get().address(), s1.address()); @@ -117,13 +118,13 @@ public void testSlices(Supplier segmentSupplier) { 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().session(), s1.session()); + assertEquals(s1.asOverlappingSlice(slice).get().scope(), s1.scope()); assertEquals(slice.asOverlappingSlice(s1).get().byteSize(), slice.byteSize()); - assertEquals(slice.asOverlappingSlice(s1).get().session(), slice.session()); + assertEquals(slice.asOverlappingSlice(s1).get().scope(), slice.scope()); if (s1.isNative()) { - assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address().addOffset(offset)); + assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address() + offset); assertEquals(slice.asOverlappingSlice(s1).get().address(), slice.address()); } assertTrue(s2.asOverlappingSlice(slice).isEmpty()); @@ -131,7 +132,7 @@ public void testSlices(Supplier segmentSupplier) { } enum OtherSegmentFactory { - NATIVE(() -> MemorySegment.allocateNative(16, MemorySession.openConfined())), + NATIVE(() -> MemorySegment.allocateNative(16, SegmentScope.auto())), HEAP(() -> MemorySegment.ofArray(new byte[]{16})); final Supplier factory; diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index 113c5039acd..3363a61134a 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -28,9 +28,10 @@ * @run testng/othervm -Xmx4G -XX:MaxDirectMemorySize=1M --enable-native-access=ALL-UNNAMED TestSegments */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -39,7 +40,6 @@ import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; @@ -50,43 +50,44 @@ public class TestSegments { @Test(dataProvider = "badSizeAndAlignments", expectedExceptions = IllegalArgumentException.class) public void testBadAllocateAlign(long size, long align) { - MemorySegment.allocateNative(size, align, MemorySession.openImplicit()); + MemorySegment.allocateNative(size, align, SegmentScope.auto()); } @Test public void testZeroLengthNativeSegment() { - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { + SegmentScope session = arena.scope(); var segment = MemorySegment.allocateNative(0, session); assertEquals(segment.byteSize(), 0); MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT); segment = MemorySegment.allocateNative(seq, session); assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % seq.byteAlignment(), 0); + assertEquals(segment.address() % seq.byteAlignment(), 0); segment = MemorySegment.allocateNative(0, 4, session); assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % 4, 0); - segment = MemorySegment.ofAddress(segment.address(), 0, session); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % 4, 0); + assertEquals(segment.address() % 4, 0); + MemorySegment rawAddress = MemorySegment.ofAddress(segment.address(), 0, session); + assertEquals(rawAddress.byteSize(), 0); + assertEquals(rawAddress.address() % 4, 0); } } @Test(expectedExceptions = { OutOfMemoryError.class, IllegalArgumentException.class }) public void testAllocateTooBig() { - MemorySegment.allocateNative(Long.MAX_VALUE, MemorySession.openImplicit()); + MemorySegment.allocateNative(Long.MAX_VALUE, SegmentScope.auto()); } @Test(expectedExceptions = OutOfMemoryError.class) public void testNativeAllocationTooBig() { - MemorySegment segment = MemorySegment.allocateNative(1024 * 1024 * 8 * 2, MemorySession.openImplicit()); // 2M + MemorySegment segment = MemorySegment.allocateNative(1024L * 1024 * 8 * 2, SegmentScope.auto()); // 2M } @Test public void testNativeSegmentIsZeroed() { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(1000, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(1000, 1, arena.scope()); for (long i = 0 ; i < segment.byteSize() ; i++) { assertEquals(0, (byte)byteHandle.get(segment, i)); } @@ -96,8 +97,8 @@ public void testNativeSegmentIsZeroed() { @Test public void testSlices() { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(10, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(10, 1, arena.scope()); //init for (byte i = 0 ; i < segment.byteSize() ; i++) { byteHandle.set(segment, (long)i, i); @@ -116,15 +117,14 @@ public void testSlices() { @Test public void testEqualsOffHeap() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(100, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); assertEquals(segment, segment.asReadOnly()); assertEquals(segment, segment.asSlice(0, 100)); assertNotEquals(segment, segment.asSlice(10, 90)); - assertNotEquals(segment, segment.asSlice(0, 90)); - assertEquals(segment, MemorySegment.ofAddress(segment.address(), 100, session.asNonCloseable())); - assertNotEquals(segment, MemorySegment.ofAddress(segment.address(), 100, MemorySession.global())); - MemorySegment segment2 = MemorySegment.allocateNative(100, session); + assertEquals(segment, segment.asSlice(0, 90)); + assertEquals(segment, MemorySegment.ofAddress(segment.address(), 100, SegmentScope.global())); + MemorySegment segment2 = MemorySegment.allocateNative(100, arena.scope()); assertNotEquals(segment, segment2); } } @@ -135,29 +135,48 @@ public void testEqualsOnHeap() { assertEquals(segment, segment.asReadOnly()); assertEquals(segment, segment.asSlice(0, 100)); assertNotEquals(segment, segment.asSlice(10, 90)); - assertNotEquals(segment, segment.asSlice(0, 90)); + assertEquals(segment, segment.asSlice(0, 90)); MemorySegment segment2 = MemorySegment.ofArray(new byte[100]); assertNotEquals(segment, segment2); } + @Test + public void testHashCodeOffHeap() { + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); + 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(), 100, SegmentScope.global()).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()); + } + @Test(expectedExceptions = IndexOutOfBoundsException.class) public void testSmallSegmentMax() { - long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when casted to int - MemorySegment memorySegment = MemorySegment.allocateNative(10, MemorySession.openImplicit()); + long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when cast to int + MemorySegment memorySegment = MemorySegment.allocateNative(10, SegmentScope.auto()); memorySegment.get(JAVA_INT, offset); } @Test(expectedExceptions = IndexOutOfBoundsException.class) public void testSmallSegmentMin() { - long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when casted to int - MemorySegment memorySegment = MemorySegment.allocateNative(10, MemorySession.openImplicit()); + long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when cast to int + MemorySegment memorySegment = MemorySegment.allocateNative(10L, SegmentScope.auto()); memorySegment.get(JAVA_INT, offset); } @Test public void testSegmentOOBMessage() { try { - var segment = MemorySegment.allocateNative(10, MemorySession.global()); + var segment = MemorySegment.allocateNative(10, SegmentScope.global()); segment.getAtIndex(ValueLayout.JAVA_INT, 2); } catch (IndexOutOfBoundsException ex) { assertTrue(ex.getMessage().contains("Out of bound access")); @@ -170,13 +189,6 @@ public void testSegmentOOBMessage() { public void testAccessModesOfFactories(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); assertFalse(segment.isReadOnly()); - tryClose(segment); - } - - static void tryClose(MemorySegment segment) { - if (segment.session().isCloseable()) { - segment.session().close(); - } } @DataProvider(name = "segmentFactories") @@ -189,45 +201,17 @@ public Object[][] segmentFactories() { () -> MemorySegment.ofArray(new int[] { 1, 2, 3, 4 }), () -> MemorySegment.ofArray(new long[] { 1l, 2l, 3l, 4l } ), () -> MemorySegment.ofArray(new short[] { 1, 2, 3, 4 } ), - () -> MemorySegment.allocateNative(4, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, 8, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(JAVA_INT, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, 8, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(JAVA_INT, MemorySession.openImplicit()) + () -> MemorySegment.allocateNative(4L, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, 8, SegmentScope.auto()), + () -> MemorySegment.allocateNative(JAVA_INT, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, 8, SegmentScope.auto()), + () -> MemorySegment.allocateNative(JAVA_INT, SegmentScope.auto()) ); return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } - static class SegmentFactory { - final MemorySession session; - final Function segmentFunc; - - SegmentFactory(MemorySession session, Function segmentFunc) { - this.session = session; - this.segmentFunc = segmentFunc; - } - - public void tryClose() { - if (session.isCloseable()) { - session.close(); - } - } - - public MemorySegment segment() { - return segmentFunc.apply(session); - } - - static SegmentFactory ofArray(Supplier segmentSupplier) { - return new SegmentFactory(MemorySession.global(), (_ignored) -> segmentSupplier.get()); - } - - static SegmentFactory ofImplicitSession(Function segmentFunc) { - return new SegmentFactory(MemorySession.openImplicit(), segmentFunc); - } - } - @Test(dataProvider = "segmentFactories") public void testFill(Supplier segmentSupplier) { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); @@ -250,41 +234,19 @@ public void testFill(Supplier segmentSupplier) { assertEquals((byte) byteHandle.get(segment, l), (byte) ~value); } assertEquals((byte) byteHandle.get(segment, segment.byteSize() - 1L), value); - tryClose(segment); - } - } - - @Test(dataProvider = "segmentFactories") - public void testFillClosed(Supplier segmentSupplier) { - MemorySegment segment = segmentSupplier.get(); - tryClose(segment); - if (!segment.session().isAlive()) { - try { - segment.fill((byte) 0xFF); - fail(); - } catch (IllegalStateException ex) { - assertTrue(true); - } } } @Test(dataProvider = "segmentFactories") public void testNativeSegments(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); - try { - segment.address(); - assertTrue(segment.isNative()); - } catch (UnsupportedOperationException exception) { - assertFalse(segment.isNative()); - } - tryClose(segment); + assertEquals(segment.isNative(), !segment.array().isPresent()); } @Test(dataProvider = "segmentFactories", expectedExceptions = UnsupportedOperationException.class) public void testFillIllegalAccessMode(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); segment.asReadOnly().fill((byte) 0xFF); - tryClose(segment); } @Test(dataProvider = "segmentFactories") @@ -302,7 +264,7 @@ public void testFillThread(Supplier segmentSupplier) throws Excep thread.start(); thread.join(); - if (segment.session().ownerThread() != null) { + if (segment.scope().isAccessibleBy(Thread.currentThread())) { RuntimeException e = exception.get(); if (!(e instanceof IllegalStateException)) { throw e; @@ -310,7 +272,6 @@ public void testFillThread(Supplier segmentSupplier) throws Excep } else { assertNull(exception.get()); } - tryClose(segment); } @Test @@ -321,22 +282,11 @@ public void testFillEmpty() { } @Test(dataProvider = "heapFactories") - public void testBigHeapSegments(IntFunction heapSegmentFactory, int factor) { - int bigSize = (Integer.MAX_VALUE / factor) + 1; - MemorySegment segment = heapSegmentFactory.apply(bigSize); - assertTrue(segment.byteSize() > 0); - } - - @Test - public void testSegmentAccessorWithWrappedLifetime() { - MemorySession session = MemorySession.openConfined(); - MemorySession publicSession = session.asNonCloseable(); - assertEquals(session, publicSession); - MemorySegment segment = publicSession.allocate(100); - assertThrows(UnsupportedOperationException.class, publicSession::close); - assertThrows(UnsupportedOperationException.class, segment.session()::close); - session.close(); - assertFalse(publicSession.isAlive()); + 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) + MemorySegment end = segment.asSlice(segment.byteSize(), 0); + assertEquals(end.address(), segment.byteSize()); // end address should be equal to segment byte size } @DataProvider(name = "badSizeAndAlignments") @@ -351,6 +301,7 @@ public Object[][] sizesAndAlignments() { @DataProvider(name = "heapFactories") public Object[][] heapFactories() { return new Object[][] { + { (IntFunction) size -> MemorySegment.ofArray(new byte[size]), 1 }, { (IntFunction) size -> MemorySegment.ofArray(new char[size]), 2 }, { (IntFunction) size -> MemorySegment.ofArray(new short[size]), 2 }, { (IntFunction) size -> MemorySegment.ofArray(new int[size]), 4 }, diff --git a/test/jdk/java/foreign/TestSharedAccess.java b/test/jdk/java/foreign/TestSharedAccess.java index e711d06e0c0..5c88b35a078 100644 --- a/test/jdk/java/foreign/TestSharedAccess.java +++ b/test/jdk/java/foreign/TestSharedAccess.java @@ -37,6 +37,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -48,8 +49,8 @@ public class TestSharedAccess { @Test public void testShared() throws Throwable { SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); - try (MemorySession session = MemorySession.openShared()) { - MemorySegment s = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openShared()) { + MemorySegment s = MemorySegment.allocateNative(layout, arena.scope());; for (int i = 0 ; i < layout.elementCount() ; i++) { setInt(s.asSlice(i * 4), 42); } @@ -93,12 +94,12 @@ public void testShared() throws Throwable { @Test public void testSharedUnsafe() throws Throwable { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment s = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openShared()) { + MemorySegment s = MemorySegment.allocateNative(4, 1, arena.scope());; setInt(s, 42); assertEquals(getInt(s), 42); List threads = new ArrayList<>(); - MemorySegment sharedSegment = MemorySegment.ofAddress(s.address(), s.byteSize(), session); + MemorySegment sharedSegment = MemorySegment.ofAddress(s.address(), s.byteSize(), arena.scope()); for (int i = 0 ; i < 1000 ; i++) { threads.add(new Thread(() -> { assertEquals(getInt(sharedSegment), 42); @@ -120,8 +121,8 @@ public void testOutsideConfinementThread() throws Throwable { CountDownLatch a = new CountDownLatch(1); CountDownLatch b = new CountDownLatch(1); CompletableFuture r; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT), arena.scope());; r = CompletableFuture.runAsync(() -> { try { ByteBuffer bb = s1.asByteBuffer(); diff --git a/test/jdk/java/foreign/TestSlices.java b/test/jdk/java/foreign/TestSlices.java index 76ce186d408..9cceaee9b75 100644 --- a/test/jdk/java/foreign/TestSlices.java +++ b/test/jdk/java/foreign/TestSlices.java @@ -22,9 +22,9 @@ * */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; @@ -46,8 +46,8 @@ public class TestSlices { @Test(dataProvider = "slices") public void testSlices(VarHandle handle, int lo, int hi, int[] values) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(LAYOUT, arena.scope());; //init for (long i = 0 ; i < 2 ; i++) { for (long j = 0 ; j < 5 ; j++) { @@ -61,8 +61,8 @@ public void testSlices(VarHandle handle, int lo, int hi, int[] values) { @Test(dataProvider = "slices") public void testSliceBadIndex(VarHandle handle, int lo, int hi, int[] values) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(LAYOUT, arena.scope());; assertThrows(() -> handle.get(segment, lo, 0)); assertThrows(() -> handle.get(segment, 0, hi)); } diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index e933706fd02..574c184522f 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -27,9 +27,10 @@ * @run testng TestSpliterator */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.invoke.VarHandle; @@ -42,6 +43,7 @@ import java.util.stream.LongStream; import java.lang.foreign.ValueLayout; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -57,8 +59,8 @@ public void testSum(int size, int threshold) { SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT); //setup - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope());; for (int i = 0; i < layout.elementCount(); i++) { INT_HANDLE.set(segment, (long) i, i); } @@ -84,7 +86,7 @@ public void testSumSameThread() { SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); //setup - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); for (int i = 0; i < layout.elementCount(); i++) { INT_HANDLE.set(segment, (long) i, i); } @@ -99,37 +101,58 @@ public void testSumSameThread() { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).spliterator(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(2, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).elements(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(2, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).spliterator(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).elements(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); + } + + @Test + public void testSpliteratorElementSizeMultipleButNotPowerOfTwo() { + MemorySegment.allocateNative(12, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); + } + + @Test + public void testStreamElementSizeMultipleButNotPowerOfTwo() { + MemorySegment.allocateNative(12, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeZero() { - MemorySegment.ofArray(new byte[7]).spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeZero() { - MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testHyperAligned() { - MemorySegment.ofArray(new byte[8]).elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(64))); + MemorySegment segment = MemorySegment.allocateNative(8, SegmentScope.auto()); + // compute an alignment constraint (in bytes) which exceed that of the native segment + long bigByteAlign = Long.lowestOneBit(segment.address()) << 1; + segment.elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(bigByteAlign * 8))); } static long sumSingle(long acc, MemorySegment segment) { diff --git a/test/jdk/java/foreign/TestStringEncoding.java b/test/jdk/java/foreign/TestStringEncoding.java index c595e671c5b..ae86e7d4ca5 100644 --- a/test/jdk/java/foreign/TestStringEncoding.java +++ b/test/jdk/java/foreign/TestStringEncoding.java @@ -22,9 +22,9 @@ * */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -39,9 +39,8 @@ public class TestStringEncoding { @Test(dataProvider = "strings") public void testStrings(String testString, int expectedByteLength) { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(expectedByteLength, session); - MemorySegment text = allocator.allocateUtf8String(testString); + try (Arena arena = Arena.openConfined()) { + MemorySegment text = arena.allocateUtf8String(testString); assertEquals(text.byteSize(), expectedByteLength); diff --git a/test/jdk/java/foreign/TestTypeAccess.java b/test/jdk/java/foreign/TestTypeAccess.java index 2739881b191..e84af14aa05 100644 --- a/test/jdk/java/foreign/TestTypeAccess.java +++ b/test/jdk/java/foreign/TestTypeAccess.java @@ -28,8 +28,8 @@ * @run testng TestTypeAccess */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.ValueLayout; import org.testng.annotations.*; @@ -53,33 +53,33 @@ public void testMemoryCoordinatePrimitive() { @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressValueGetAsString() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - String address = (String)ADDR_HANDLE.get(s.address()); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + String address = (String)ADDR_HANDLE.get(s); } } @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressValueSetAsString() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - ADDR_HANDLE.set(s.address(), "string"); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + ADDR_HANDLE.set(s, "string"); } } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryAddressValueGetAsPrimitive() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - int address = (int)ADDR_HANDLE.get(s.address()); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + int address = (int)ADDR_HANDLE.get(s); } } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryAddressValueSetAsPrimitive() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - ADDR_HANDLE.set(s.address(), 1); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + ADDR_HANDLE.set(s, 1); } } diff --git a/test/jdk/java/foreign/TestUnsupportedLinker.java b/test/jdk/java/foreign/TestUnsupportedLinker.java index 8d223919b97..d16ba1646b2 100644 --- a/test/jdk/java/foreign/TestUnsupportedLinker.java +++ b/test/jdk/java/foreign/TestUnsupportedLinker.java @@ -29,8 +29,7 @@ */ import java.lang.foreign.Linker; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import java.lang.foreign.ValueLayout; @@ -50,11 +49,11 @@ public void testEmptyVaList() { @Test(expectedExceptions = UnsupportedOperationException.class) public void testNonEmptyVaList() { - VaList.make(builder -> builder.addVarg(ValueLayout.JAVA_INT, 42), MemorySession.openImplicit()); + VaList.make(builder -> builder.addVarg(ValueLayout.JAVA_INT, 42), SegmentScope.auto()); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testUnsafeVaList() { - VaList.ofAddress(MemoryAddress.NULL, MemorySession.openImplicit()); + VaList.ofAddress(0L, SegmentScope.auto()); } } diff --git a/test/jdk/java/foreign/TestUpcallAsync.java b/test/jdk/java/foreign/TestUpcallAsync.java index 64573029588..4463bc0475c 100644 --- a/test/jdk/java/foreign/TestUpcallAsync.java +++ b/test/jdk/java/foreign/TestUpcallAsync.java @@ -33,15 +33,15 @@ * TestUpcallAsync */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; + import org.testng.annotations.Test; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.ArrayList; @@ -61,24 +61,24 @@ public class TestUpcallAsync extends TestUpcallBase { public void testUpcallsAsync(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); - try (MemorySession session = MemorySession.openShared()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment addr = findNativeOrThrow(fName); + try (Arena arena = Arena.openShared()) { FunctionDescriptor descriptor = function(ret, paramTypes, fields); - MethodHandle mh = downcallHandle(ABI, addr, allocator, descriptor); - Object[] args = makeArgs(MemorySession.openImplicit(), ret, paramTypes, fields, returnChecks, argChecks); + MethodHandle mh = downcallHandle(ABI, addr, arena, descriptor); + Object[] args = makeArgs(SegmentScope.auto(), ret, paramTypes, fields, returnChecks, argChecks); mh = mh.asSpreader(Object[].class, args.length); mh = MethodHandles.insertArguments(mh, 0, (Object) args); FunctionDescriptor callbackDesc = descriptor.returnLayout() .map(FunctionDescriptor::of) .orElse(FunctionDescriptor.ofVoid()); - Addressable callback = ABI.upcallStub(mh.asType(Linker.upcallType(callbackDesc)), callbackDesc, session); + MemorySegment callback = ABI.upcallStub(mh, callbackDesc, arena.scope()); MethodHandle invoker = asyncInvoker(ret, ret == Ret.VOID ? null : paramTypes.get(0), fields); - Object res = invoker.type().returnType() == MemorySegment.class - ? invoker.invoke(allocator, callback) + Object res = (descriptor.returnLayout().isPresent() && + descriptor.returnLayout().get() instanceof GroupLayout) + ? invoker.invoke(arena.scope(), callback) : invoker.invoke(callback); argChecks.forEach(c -> c.accept(args)); if (ret == Ret.NON_VOID) { @@ -102,7 +102,7 @@ private MethodHandle asyncInvoker(Ret ret, ParamType returnType, List { - Addressable invokerSymbol = findNativeOrThrow(symbol); + MemorySegment invokerSymbol = findNativeOrThrow(symbol); MemoryLayout returnLayout = returnType.layout(fields); FunctionDescriptor desc = FunctionDescriptor.of(returnLayout, C_POINTER); diff --git a/test/jdk/java/foreign/TestUpcallBase.java b/test/jdk/java/foreign/TestUpcallBase.java index a9b750d8219..85da103a801 100644 --- a/test/jdk/java/foreign/TestUpcallBase.java +++ b/test/jdk/java/foreign/TestUpcallBase.java @@ -22,10 +22,10 @@ * */ -import java.lang.foreign.Addressable; +import java.lang.foreign.GroupLayout; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; @@ -34,6 +34,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -54,17 +55,17 @@ public abstract class TestUpcallBase extends CallGeneratorHelper { try { DUMMY = MethodHandles.lookup().findStatic(TestUpcallBase.class, "dummy", MethodType.methodType(void.class)); PASS_AND_SAVE = MethodHandles.lookup().findStatic(TestUpcallBase.class, "passAndSave", - MethodType.methodType(Object.class, Object[].class, AtomicReference.class, int.class)); + MethodType.methodType(Object.class, Object[].class, AtomicReference.class, int.class, List.class)); } catch (Throwable ex) { throw new IllegalStateException(ex); } } - private static Addressable DUMMY_STUB; + private static MemorySegment DUMMY_STUB; @BeforeClass void setup() { - DUMMY_STUB = ABI.upcallStub(DUMMY, FunctionDescriptor.ofVoid(), MemorySession.openImplicit()); + DUMMY_STUB = ABI.upcallStub(DUMMY, FunctionDescriptor.ofVoid(), SegmentScope.auto()); } static FunctionDescriptor function(Ret ret, List params, List fields) { @@ -80,11 +81,11 @@ static FunctionDescriptor function(Ret ret, List params, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { + static Object[] makeArgs(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { return makeArgs(session, ret, params, fields, checks, argChecks, List.of()); } - static Object[] makeArgs(MemorySession session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) throws ReflectiveOperationException { + static Object[] makeArgs(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) throws ReflectiveOperationException { Object[] args = new Object[prefix.size() + params.size() + 1]; int argNum = 0; for (MemoryLayout layout : prefix) { @@ -97,27 +98,32 @@ static Object[] makeArgs(MemorySession session, Ret ret, List params, return args; } - static Addressable makeCallback(MemorySession session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) { + static MemorySegment makeCallback(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) { if (params.isEmpty()) { return DUMMY_STUB; } AtomicReference box = new AtomicReference<>(); - MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box, prefix.size()); + List layouts = new ArrayList<>(); + layouts.addAll(prefix); + for (int i = 0 ; i < params.size() ; i++) { + layouts.add(params.get(i).layout(fields)); + } + MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box, prefix.size(), layouts); mh = mh.asCollector(Object[].class, prefix.size() + params.size()); for(int i = 0; i < prefix.size(); i++) { - mh = mh.asType(mh.type().changeParameterType(i, carrier(prefix.get(i), false))); + mh = mh.asType(mh.type().changeParameterType(i, carrier(prefix.get(i)))); } for (int i = 0; i < params.size(); i++) { ParamType pt = params.get(i); MemoryLayout layout = pt.layout(fields); - Class carrier = carrier(layout, false); + Class carrier = carrier(layout); mh = mh.asType(mh.type().changeParameterType(prefix.size() + i, carrier)); final int finalI = prefix.size() + i; - if (carrier == MemorySegment.class) { + if (layout instanceof GroupLayout) { argChecks.add(o -> assertStructEquals((MemorySegment) box.get()[finalI], (MemorySegment) o[finalI], layout)); } else { argChecks.add(o -> assertEquals(box.get()[finalI], o[finalI])); @@ -126,9 +132,8 @@ static Addressable makeCallback(MemorySession session, Ret ret, List ParamType firstParam = params.get(0); MemoryLayout firstlayout = firstParam.layout(fields); - Class firstCarrier = carrier(firstlayout, true); - - if (firstCarrier == MemorySegment.class) { + Class firstCarrier = carrier(firstlayout); + if (firstlayout instanceof GroupLayout) { checks.add(o -> assertStructEquals((MemorySegment) box.get()[prefix.size()], (MemorySegment) o, firstlayout)); } else { checks.add(o -> assertEquals(o, box.get()[prefix.size()])); @@ -143,11 +148,11 @@ static Addressable makeCallback(MemorySession session, Ret ret, List return ABI.upcallStub(mh, func, session); } - static Object passAndSave(Object[] o, AtomicReference ref, int retArg) { + static Object passAndSave(Object[] o, AtomicReference ref, int retArg, List layouts) { for (int i = 0; i < o.length; i++) { - if (o[i] instanceof MemorySegment) { + if (layouts.get(i) instanceof GroupLayout) { MemorySegment ms = (MemorySegment) o[i]; - MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), MemorySession.openImplicit()); + MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), SegmentScope.auto()); copy.copyFrom(ms); o[i] = copy; } diff --git a/test/jdk/java/foreign/TestUpcallException.java b/test/jdk/java/foreign/TestUpcallException.java index c27fde54dc0..d9dc32bacb2 100644 --- a/test/jdk/java/foreign/TestUpcallException.java +++ b/test/jdk/java/foreign/TestUpcallException.java @@ -33,71 +33,26 @@ * TestUpcallException */ -import jdk.test.lib.Utils; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Paths; -import java.util.List; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertTrue; +public class TestUpcallException extends UpcallTestHelper { -public class TestUpcallException { - - @Test - public void testExceptionInterpreted() throws InterruptedException, IOException { - run(/* useSpec = */ false, /* isVoid = */ true); - run(/* useSpec = */ false, /* isVoid = */ false); - } - - @Test - public void testExceptionSpecialized() throws IOException, InterruptedException { - run(/* useSpec = */ true, /* isVoid = */ true); - run(/* useSpec = */ true, /* isVoid = */ false); - } - - private void run(boolean useSpec, boolean isVoid) throws IOException, InterruptedException { - Process process = new ProcessBuilder() - .command( - Paths.get(Utils.TEST_JDK) - .resolve("bin") - .resolve("java") - .toAbsolutePath() - .toString(), - "--enable-preview", - "--enable-native-access=ALL-UNNAMED", - "-Djava.library.path=" + System.getProperty("java.library.path"), - "-Djdk.internal.foreign.ProgrammableUpcallHandler.USE_SPEC=" + useSpec, - "-cp", Utils.TEST_CLASS_PATH, - "ThrowingUpcall", - isVoid ? "void" : "non-void") - .start(); - - int result = process.waitFor(); - assertNotEquals(result, 0); - - List outLines = linesFromStream(process.getInputStream()); - outLines.forEach(System.out::println); - List errLines = linesFromStream(process.getErrorStream()); - errLines.forEach(System.err::println); - - // Exception message would be found in stack trace - String shouldInclude = "Testing upcall exceptions"; - assertTrue(linesContain(errLines, shouldInclude), "Did not find '" + shouldInclude + "' in stderr"); - } - - private boolean linesContain(List errLines, String shouldInclude) { - return errLines.stream().anyMatch(line -> line.contains(shouldInclude)); + @Test(dataProvider = "cases") + public void testException(boolean useSpec, boolean isVoid) throws InterruptedException, IOException { + runInNewProcess(ThrowingUpcall.class, useSpec, isVoid ? "void" : "") + .assertStdErrContains("Testing upcall exceptions"); } - private static List linesFromStream(InputStream stream) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { - return reader.lines().toList(); - } + @DataProvider + public static Object[][] cases() { + return new Object[][]{ + { false, true, }, + { false, false, }, + { true, true, }, + { true, false, } + }; } } diff --git a/test/jdk/java/foreign/TestUpcallHighArity.java b/test/jdk/java/foreign/TestUpcallHighArity.java index f36da3bb948..54e34fa2f9c 100644 --- a/test/jdk/java/foreign/TestUpcallHighArity.java +++ b/test/jdk/java/foreign/TestUpcallHighArity.java @@ -33,16 +33,17 @@ * TestUpcallHighArity */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -76,17 +77,17 @@ public class TestUpcallHighArity extends CallGeneratorHelper { S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER) ); MH_passAndSave = MethodHandles.lookup().findStatic(TestUpcallHighArity.class, "passAndSave", - MethodType.methodType(void.class, Object[].class, AtomicReference.class)); + MethodType.methodType(void.class, Object[].class, AtomicReference.class, List.class)); } catch (ReflectiveOperationException e) { throw new InternalError(e); } } - static void passAndSave(Object[] o, AtomicReference ref) { + static void passAndSave(Object[] o, AtomicReference ref, List layouts) { for (int i = 0; i < o.length; i++) { - if (o[i] instanceof MemorySegment) { + if (layouts.get(i) instanceof GroupLayout) { MemorySegment ms = (MemorySegment) o[i]; - MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), MemorySession.openImplicit()); + MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), SegmentScope.auto()); copy.copyFrom(ms); o[i] = copy; } @@ -98,11 +99,11 @@ static void passAndSave(Object[] o, AtomicReference ref) { public void testUpcall(MethodHandle downcall, MethodType upcallType, FunctionDescriptor upcallDescriptor) throws Throwable { AtomicReference capturedArgs = new AtomicReference<>(); - MethodHandle target = MethodHandles.insertArguments(MH_passAndSave, 1, capturedArgs) + MethodHandle target = MethodHandles.insertArguments(MH_passAndSave, 1, capturedArgs, upcallDescriptor.argumentLayouts()) .asCollector(Object[].class, upcallType.parameterCount()) .asType(upcallType); - try (MemorySession session = MemorySession.openConfined()) { - Addressable upcallStub = LINKER.upcallStub(target, upcallDescriptor, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment upcallStub = LINKER.upcallStub(target, upcallDescriptor, arena.scope()); Object[] args = new Object[upcallType.parameterCount() + 1]; args[0] = upcallStub; List argLayouts = upcallDescriptor.argumentLayouts(); @@ -114,7 +115,7 @@ public void testUpcall(MethodHandle downcall, MethodType upcallType, Object[] capturedArgsArr = capturedArgs.get(); for (int i = 0; i < capturedArgsArr.length; i++) { - if (upcallType.parameterType(i) == MemorySegment.class) { + if (upcallDescriptor.argumentLayouts().get(i) instanceof GroupLayout) { assertStructEquals((MemorySegment) capturedArgsArr[i], (MemorySegment) args[i + 1], argLayouts.get(i)); } else { assertEquals(capturedArgsArr[i], args[i + 1], "For index " + i); @@ -128,10 +129,10 @@ public static Object[][] args() { return new Object[][]{ { MH_do_upcall, MethodType.methodType(void.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class), + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class), FunctionDescriptor.ofVoid( S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, diff --git a/test/jdk/java/foreign/TestUpcallScope.java b/test/jdk/java/foreign/TestUpcallScope.java index e5bb77c6af2..f59e9c0d427 100644 --- a/test/jdk/java/foreign/TestUpcallScope.java +++ b/test/jdk/java/foreign/TestUpcallScope.java @@ -32,9 +32,9 @@ * TestUpcallScope */ -import java.lang.foreign.Addressable; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -52,11 +52,10 @@ public class TestUpcallScope extends TestUpcallBase { public void testUpcalls(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MethodHandle mh = downcallHandle(ABI, addr, allocator, function(ret, paramTypes, fields)); - Object[] args = makeArgs(session, ret, paramTypes, fields, returnChecks, argChecks); + MemorySegment addr = findNativeOrThrow(fName); + try (Arena arena = Arena.openConfined()) { + MethodHandle mh = downcallHandle(ABI, addr, arena, function(ret, paramTypes, fields)); + Object[] args = makeArgs(arena.scope(), ret, paramTypes, fields, returnChecks, argChecks); Object[] callArgs = args; Object res = mh.invokeWithArguments(callArgs); argChecks.forEach(c -> c.accept(args)); diff --git a/test/jdk/java/foreign/TestUpcallStack.java b/test/jdk/java/foreign/TestUpcallStack.java index 9454d77a996..5df32ec2af6 100644 --- a/test/jdk/java/foreign/TestUpcallStack.java +++ b/test/jdk/java/foreign/TestUpcallStack.java @@ -32,10 +32,11 @@ * TestUpcallStack */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -53,11 +54,10 @@ public class TestUpcallStack extends TestUpcallBase { public void testUpcallsStack(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow("s" + fName); - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MethodHandle mh = downcallHandle(ABI, addr, allocator, functionStack(ret, paramTypes, fields)); - Object[] args = makeArgsStack(session, ret, paramTypes, fields, returnChecks, argChecks); + MemorySegment addr = findNativeOrThrow("s" + fName); + try (Arena arena = Arena.openConfined()) { + MethodHandle mh = downcallHandle(ABI, addr, arena, functionStack(ret, paramTypes, fields)); + Object[] args = makeArgsStack(arena.scope(), ret, paramTypes, fields, returnChecks, argChecks); Object[] callArgs = args; Object res = mh.invokeWithArguments(callArgs); argChecks.forEach(c -> c.accept(args)); @@ -71,7 +71,7 @@ static FunctionDescriptor functionStack(Ret ret, List params, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { + static Object[] makeArgsStack(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { return makeArgs(session, ret, params, fields, checks, argChecks, STACK_PREFIX_LAYOUTS); } diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index ca2cab17d58..680893cd57f 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -37,12 +37,12 @@ * TestUpcallStructScope */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -89,14 +89,14 @@ public void testUpcall() throws Throwable { AtomicReference capturedSegment = new AtomicReference<>(); MethodHandle target = methodHandle(capturedSegment::set); FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(S_PDI_LAYOUT); - try (MemorySession session = MemorySession.openConfined()) { - Addressable upcallStub = LINKER.upcallStub(target, upcallDesc, session); - MemorySegment argSegment = MemorySegment.allocateNative(S_PDI_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment upcallStub = LINKER.upcallStub(target, upcallDesc, arena.scope()); + MemorySegment argSegment = MemorySegment.allocateNative(S_PDI_LAYOUT, arena.scope());; MH_do_upcall.invoke(upcallStub, argSegment); } MemorySegment captured = capturedSegment.get(); - assertFalse(captured.session().isAlive()); + assertFalse(captured.scope().isAlive()); } } diff --git a/test/jdk/java/foreign/TestValueLayouts.java b/test/jdk/java/foreign/TestValueLayouts.java new file mode 100644 index 00000000000..56019f907a8 --- /dev/null +++ b/test/jdk/java/foreign/TestValueLayouts.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019, 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 + * @enablePreview + * @modules java.base/jdk.internal.misc + * @run testng 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.*; + +public class TestValueLayouts { + + @Test + public void testByte() { + testAligned(JAVA_BYTE, byte.class, Byte.SIZE); + } + + @Test + public void testBoolean() { + testAligned(JAVA_BOOLEAN, boolean.class, Byte.SIZE); + } + + @Test + public void testShort() { + testAligned(JAVA_SHORT, short.class, Short.SIZE); + } + + @Test + public void testShortUnaligned() { + testUnaligned(JAVA_SHORT_UNALIGNED, short.class, Short.SIZE); + } + + @Test + public void testInt() { + testAligned(JAVA_INT, int.class, Integer.SIZE); + } + + @Test + public void testIntUnaligned() { + testUnaligned(JAVA_INT_UNALIGNED, int.class, Integer.SIZE); + } + + @Test + public void testLong() { + testAligned(JAVA_LONG, long.class, Long.SIZE); + } + + @Test + public void testLongUnaligned() { + testUnaligned(JAVA_LONG_UNALIGNED, long.class, Long.SIZE); + } + + @Test + public void testFloat() { + testAligned(JAVA_FLOAT, float.class, Float.SIZE); + } + + @Test + public void testFloatUnaligned() { + testUnaligned(JAVA_FLOAT_UNALIGNED, float.class, Float.SIZE); + } + + @Test + public void testDouble() { + testAligned(JAVA_DOUBLE, double.class, Double.SIZE); + } + + @Test + public void testDoubleUnaligned() { + testUnaligned(JAVA_DOUBLE_UNALIGNED, double.class, Double.SIZE); + } + + @Test + public void testChar() { + testAligned(JAVA_CHAR, char.class, Character.SIZE); + } + + @Test + public void testCharUnaligned() { + testUnaligned(JAVA_CHAR_UNALIGNED, char.class, Character.SIZE); + } + + @Test + public void testAddress() { + testAligned(ADDRESS, MemorySegment.class, Unsafe.ADDRESS_SIZE * 8L); + } + + @Test + public void testAddressUnaligned() { + testUnaligned(ADDRESS_UNALIGNED, MemorySegment.class, Unsafe.ADDRESS_SIZE * 8L); + } + + void testAligned(ValueLayout layout, + Class carrier, + long bitSize) { + test(layout, carrier, bitSize, bitSize); + } + + void testUnaligned(ValueLayout layout, + Class carrier, + long bitSize) { + test(layout, carrier, bitSize, Byte.SIZE); + } + + void test(ValueLayout layout, + Class carrier, + long bitSize, + long bitAlignment) { + assertEquals(layout.carrier(), carrier); + assertEquals(layout.bitSize(), bitSize); + assertEquals(layout.order(), ByteOrder.nativeOrder()); + assertEquals(layout.bitAlignment(), bitAlignment); + assertTrue(layout.name().isEmpty()); + assertEquals(layout.byteSize(), layout.bitSize() / 8); + assertEquals(layout.byteAlignment(), layout.bitAlignment() / 8); + + } + +} diff --git a/test/jdk/java/foreign/TestVarArgs.java b/test/jdk/java/foreign/TestVarArgs.java index bd485bc0c0e..90ad9842d3d 100644 --- a/test/jdk/java/foreign/TestVarArgs.java +++ b/test/jdk/java/foreign/TestVarArgs.java @@ -29,13 +29,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 TestVarArgs */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import org.testng.annotations.Test; @@ -59,26 +57,26 @@ public class TestVarArgs extends CallGeneratorHelper { System.loadLibrary("VarArgs"); try { MH_CHECK = MethodHandles.lookup().findStatic(TestVarArgs.class, "check", - MethodType.methodType(void.class, int.class, MemoryAddress.class, List.class)); + MethodType.methodType(void.class, int.class, MemorySegment.class, List.class)); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } } - static final Addressable VARARGS_ADDR = findNativeOrThrow("varargs"); + static final MemorySegment VARARGS_ADDR = findNativeOrThrow("varargs"); @Test(dataProvider = "functions") public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff List paramTypes, List fields) throws Throwable { List args = makeArgs(paramTypes, fields); - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle checker = MethodHandles.insertArguments(MH_CHECK, 2, args); - MemorySegment writeBack = LINKER.upcallStub(checker, FunctionDescriptor.ofVoid(C_INT, C_POINTER), session); - MemorySegment callInfo = MemorySegment.allocateNative(CallInfo.LAYOUT, session); - MemorySegment argIDs = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(args.size(), C_INT), session); + MemorySegment writeBack = LINKER.upcallStub(checker, FunctionDescriptor.ofVoid(C_INT, C_POINTER), arena.scope()); + MemorySegment callInfo = MemorySegment.allocateNative(CallInfo.LAYOUT, arena.scope());; + MemorySegment argIDs = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(args.size(), C_INT), arena.scope());; - MemoryAddress callInfoPtr = callInfo.address(); + MemorySegment callInfoPtr = callInfo; CallInfo.writeback(callInfo, writeBack); CallInfo.argIDs(callInfo, argIDs); @@ -91,10 +89,11 @@ public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff argLayouts.add(C_POINTER); // call info argLayouts.add(C_INT); // size - FunctionDescriptor desc = FunctionDescriptor.ofVoid(argLayouts.toArray(MemoryLayout[]::new)) - .asVariadic(args.stream().map(a -> a.layout).toArray(MemoryLayout[]::new)); + FunctionDescriptor baseDesc = FunctionDescriptor.ofVoid(argLayouts.toArray(MemoryLayout[]::new)); + Linker.Option varargIndex = Linker.Option.firstVariadicArg(baseDesc.argumentLayouts().size()); + FunctionDescriptor desc = baseDesc.appendArgumentLayouts(args.stream().map(a -> a.layout).toArray(MemoryLayout[]::new)); - MethodHandle downcallHandle = LINKER.downcallHandle(VARARGS_ADDR, desc); + MethodHandle downcallHandle = LINKER.downcallHandle(VARARGS_ADDR, desc, varargIndex); List argValues = new ArrayList<>(); argValues.add(callInfoPtr); // call info @@ -121,13 +120,13 @@ private static List makeArgs(List paramTypes, List args) { + private static void check(int index, MemorySegment ptr, List args) { Arg varArg = args.get(index); MemoryLayout layout = varArg.layout; MethodHandle getter = varArg.getter; List> checks = varArg.checks; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.ofAddress(ptr, layout.byteSize(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.ofAddress(ptr.address(), layout.byteSize(), arena.scope()); Object obj = getter.invoke(seg); checks.forEach(check -> check.accept(obj)); } catch (Throwable e) { @@ -143,11 +142,11 @@ private static class CallInfo { static final VarHandle VH_writeback = LAYOUT.varHandle(groupElement("writeback")); static final VarHandle VH_argIDs = LAYOUT.varHandle(groupElement("argIDs")); - static void writeback(MemorySegment seg, Addressable addr) { - VH_writeback.set(seg, addr.address()); + static void writeback(MemorySegment seg, MemorySegment addr) { + VH_writeback.set(seg, addr); } - static void argIDs(MemorySegment seg, Addressable addr) { - VH_argIDs.set(seg, addr.address()); + static void argIDs(MemorySegment seg, MemorySegment addr) { + VH_argIDs.set(seg, addr); } } diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index e09d6292098..28b05d02d62 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -28,7 +28,8 @@ * @run testng TestVarHandleCombinators */ -import java.lang.foreign.MemorySession; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.Test; @@ -65,7 +66,7 @@ public void testUnalignedElement() { public void testAlign() { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_BYTE.withBitAlignment(16)); - MemorySegment segment = MemorySegment.allocateNative(1, 2, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(1L, 2, SegmentScope.auto()); vh.set(segment, 0L, (byte) 10); // fine, memory region is aligned assertEquals((byte) vh.get(segment, 0L), (byte) 10); } @@ -101,8 +102,8 @@ public void testNestedSequenceAccess() { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT.withBitAlignment(32)); int count = 0; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(inner_size * outer_size * 8, 4, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(inner_size * outer_size * 8, 4, arena.scope());; for (long i = 0; i < outer_size; i++) { for (long j = 0; j < inner_size; j++) { vh.set(segment, i * 40 + j * 8, count); diff --git a/test/jdk/java/foreign/ThrowingUpcall.java b/test/jdk/java/foreign/ThrowingUpcall.java index 40ea4e51a70..70d2aba66ec 100644 --- a/test/jdk/java/foreign/ThrowingUpcall.java +++ b/test/jdk/java/foreign/ThrowingUpcall.java @@ -21,10 +21,10 @@ * questions. */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -72,8 +72,8 @@ public static void testVoid() throws Throwable { MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(void.class)); handle = MethodHandles.insertArguments(invoker, 0, handle); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), arena.scope()); downcallVoid.invoke(stub); // should call Shutdown.exit(1); } @@ -85,8 +85,8 @@ public static void testNonVoid() throws Throwable { MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(int.class, int.class)); handle = MethodHandles.insertArguments(invoker, 0, handle); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.of(C_INT, C_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.of(C_INT, C_INT), arena.scope()); downcallNonVoid.invoke(42, stub); // should call Shutdown.exit(1); } diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java new file mode 100644 index 00000000000..fa4ff862d51 --- /dev/null +++ b/test/jdk/java/foreign/UpcallTestHelper.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 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. + */ + +import jdk.test.lib.Utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertTrue; + +public class UpcallTestHelper extends NativeTestHelper { + public record Output(List stdout, List stderr) { + private static void assertContains(List lines, String shouldInclude) { + assertTrue(lines.stream().anyMatch(line -> line.contains(shouldInclude)), + "Did not find '" + shouldInclude + "' in stderr"); + } + + public void assertStdErrContains(String shouldInclude) { + assertContains(stderr, shouldInclude); + } + } + + public Output runInNewProcess(Class target, boolean useSpec, String... programArgs) throws IOException, InterruptedException { + assert !target.isArray(); + + List command = new ArrayList<>(List.of( + Paths.get(Utils.TEST_JDK) + .resolve("bin") + .resolve("java") + .toAbsolutePath() + .toString(), + "--enable-preview", + "--enable-native-access=ALL-UNNAMED", + "-Djava.library.path=" + System.getProperty("java.library.path"), + "-Djdk.internal.foreign.ProgrammableUpcallHandler.USE_SPEC=" + useSpec, + "-cp", Utils.TEST_CLASS_PATH, + target.getName() + )); + command.addAll(Arrays.asList(programArgs)); + Process process = new ProcessBuilder() + .command(command) + .start(); + + int result = process.waitFor(); + assertNotEquals(result, 0); + + List outLines = linesFromStream(process.getInputStream()); + outLines.forEach(System.out::println); + List errLines = linesFromStream(process.getErrorStream()); + errLines.forEach(System.err::println); + + return new Output(outLines, errLines); + } + + private static List linesFromStream(InputStream stream) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { + return reader.lines().toList(); + } + } +} diff --git a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java index 190df4e96a5..037db225c65 100644 --- a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java +++ b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java @@ -32,16 +32,17 @@ public class CallArrangerTestBase { public static void checkArgumentBindings(CallingSequence callingSequence, Binding[][] argumentBindings) { - assertEquals(callingSequence.argumentBindingsCount(), argumentBindings.length); + assertEquals(callingSequence.argumentBindingsCount(), argumentBindings.length, + 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)); + assertEquals(actual, Arrays.asList(expected), "bindings at: " + i + ": " + actual + " != " + Arrays.toString(expected)); } } public static void checkReturnBindings(CallingSequence callingSequence, Binding[] returnBindings) { - assertEquals(callingSequence.returnBindings(), Arrays.asList(returnBindings)); + assertEquals(callingSequence.returnBindings(), Arrays.asList(returnBindings), callingSequence.returnBindings() + " != " + Arrays.toString(returnBindings)); } } diff --git a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java index a2c49e50432..6b33f237b60 100644 --- a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java @@ -25,6 +25,7 @@ /* * @test * @enablePreview + * @requires sun.arch.data.model == "64" * @modules java.base/jdk.internal.foreign * java.base/jdk.internal.foreign.abi * java.base/jdk.internal.foreign.abi.aarch64 @@ -32,42 +33,50 @@ * @run testng TestAarch64CallArranger */ -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.StructLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +import jdk.internal.foreign.abi.LinkerOptions; +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; +import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.AArch64.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; +import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; + import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class TestAarch64CallArranger extends CallArrangerTestBase { + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + private static final VMStorage RETURN_BUFFER_STORAGE = StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) } + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -85,13 +94,13 @@ public void testInteger() { C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(r2, int.class) }, @@ -100,8 +109,8 @@ public void testInteger() { { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), int.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 8), int.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -115,13 +124,13 @@ public void testTwoIntTwoFloat() { C_INT, C_INT, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -137,13 +146,13 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, expectedBindings }); @@ -165,7 +174,7 @@ public static Object[][] structs() { // struct s { int32_t a, b; double c; int32_t d }; { struct2, new Binding[] { copy(struct2), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r0, long.class) }}, // struct s { int32_t a[2]; float b[2] }; @@ -197,21 +206,21 @@ public void testMultipleStructs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct1, struct2, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct1), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r0, long.class) }, { copy(struct2), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r1, long.class) }, { vmStore(r2, int.class) } @@ -228,13 +237,13 @@ public void testReturnStruct1() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class)); + 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)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(r8, long.class) @@ -252,14 +261,14 @@ public void testReturnStruct2() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, Addressable.class)); + 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)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r10, long.class) }, - { unboxAddress(Addressable.class), vmStore(r9, long.class) } + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{ @@ -281,14 +290,14 @@ public void testStructHFA1() { FunctionDescriptor fd = FunctionDescriptor.of(hfa, C_FLOAT, C_INT, hfa); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, Addressable.class)); + 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)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r10, long.class) }, - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(v0, float.class) }, { vmStore(r0, int.class) }, { @@ -319,13 +328,13 @@ public void testStructHFA3() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct, struct, struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, float.class), @@ -349,9 +358,9 @@ public void testStructHFA3() { { dup(), bufferLoad(0, long.class), - vmStore(stackStorage(0), long.class), + vmStore(stackStorage((short) 8, 0), long.class), bufferLoad(8, int.class), - vmStore(stackStorage(1), int.class), + vmStore(stackStorage((short) 4, 8), int.class), } }); @@ -373,23 +382,23 @@ public void testStructStackSpill() { struct, struct, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, struct, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(r0, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(r1, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { copy(struct), unboxAddress(), vmStore(r0, long.class) }, + { copy(struct), unboxAddress(), vmStore(r1, long.class) }, { vmStore(r2, int.class) }, { vmStore(r3, int.class) }, { vmStore(r4, int.class) }, { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), int.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage((short) 8, 0), long.class) }, + { vmStore(stackStorage((short) 4, 8), int.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -398,18 +407,18 @@ public void testStructStackSpill() { @Test public void testVarArgsInRegs() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); - FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(1))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -421,21 +430,218 @@ public void testVarArgsInRegs() { @Test public void testVarArgsOnStack() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); - FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(1))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); // The two variadic arguments should be allocated on the stack checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), float.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 8), float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack() { + MethodType mt = MethodType.methodType(void.class, + int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, + int.class, int.class, short.class, byte.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_INT, C_INT, C_INT, C_INT, + C_INT, C_INT, C_INT, C_INT, + C_INT, C_INT, C_SHORT, C_CHAR); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, int.class) }, + { vmStore(r1, int.class) }, + { vmStore(r2, int.class) }, + { vmStore(r3, int.class) }, + { vmStore(r4, int.class) }, + { vmStore(r5, int.class) }, + { vmStore(r6, int.class) }, + { vmStore(r7, int.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 4), int.class) }, + { cast(short.class, int.class), vmStore(stackStorage((short) 2, 8), int.class) }, + { cast(byte.class, int.class), vmStore(stackStorage((short) 1, 10), int.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack2() { + StructLayout struct = MemoryLayout.structLayout( + C_FLOAT, + C_FLOAT + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + int.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_INT, struct); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { + dup(), + bufferLoad(0, int.class), + vmStore(stackStorage((short) 4, 4), int.class), + bufferLoad(4, int.class), + vmStore(stackStorage((short) 4, 8), int.class), + } + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack3() { + StructLayout struct = MemoryLayout.structLayout( + C_POINTER, + C_POINTER + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + MemorySegment.class, float.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + struct, C_FLOAT); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { dup(), + bufferLoad(0, long.class), vmStore(stackStorage((short) 8, 0), long.class), + bufferLoad(8, long.class), vmStore(stackStorage((short) 8, 8), long.class) }, + { vmStore(stackStorage((short) 4, 16), float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack4() { + StructLayout struct = MemoryLayout.structLayout( + C_INT, + C_INT, + C_POINTER + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + float.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_FLOAT, struct); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { vmStore(stackStorage((short) 4, 0), float.class) }, + { dup(), + bufferLoad(0, long.class), vmStore(stackStorage((short) 8, 8), long.class), + bufferLoad(8, long.class), vmStore(stackStorage((short) 8, 16), long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index 1e8da4fd456..a17d3b79af7 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -34,47 +34,53 @@ */ import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +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.foreign.Addressable; import java.lang.invoke.MethodType; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.SysV.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; + import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class TestSysVCallArranger extends CallArrangerTestBase { + private static final short STACK_SLOT_SIZE = 8; + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + private static final VMStorage RETURN_BUFFER_STORAGE = StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rax, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -90,13 +96,13 @@ public void testNestedStructs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, int.class), vmStore(rsi, int.class)}, { vmStore(rax, long.class) }, @@ -104,7 +110,7 @@ public void testNestedStructs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -121,13 +127,13 @@ public void testNestedUnion() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, long.class), vmStore(rsi, long.class)}, { vmStore(rax, long.class) }, @@ -135,7 +141,7 @@ public void testNestedUnion() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -151,21 +157,21 @@ public void testNestedStructsUnaligned() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, - { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class)}, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { dup(), bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class)}, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -181,21 +187,21 @@ public void testNestedUnionUnaligned() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, - { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), - bufferLoad(8, int.class), vmStore(stackStorage(1), int.class)}, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { dup(), bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), + bufferLoad(8, int.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class)}, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -206,13 +212,13 @@ public void testIntegerRegs() { C_INT, C_INT, C_INT, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { vmStore(rdx, int.class) }, @@ -224,7 +230,7 @@ public void testIntegerRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -237,13 +243,13 @@ public void testDoubleRegs() { C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -257,7 +263,7 @@ public void testDoubleRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 8); + assertEquals(bindings.nVectorArgs(), 8); } @Test @@ -272,21 +278,21 @@ public void testMixed() { C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, long.class) }, { vmStore(rsi, long.class) }, { vmStore(rdx, long.class) }, { vmStore(rcx, long.class) }, { vmStore(r8, long.class) }, { vmStore(r9, long.class) }, - { vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class) }, { vmStore(xmm0, float.class) }, { vmStore(xmm1, float.class) }, { vmStore(xmm2, float.class) }, @@ -295,14 +301,14 @@ public void testMixed() { { vmStore(xmm5, float.class) }, { vmStore(xmm6, float.class) }, { vmStore(xmm7, float.class) }, - { vmStore(stackStorage(2), float.class) }, - { vmStore(stackStorage(3), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), float.class) }, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 8); + assertEquals(bindings.nVectorArgs(), 8); } /** @@ -329,13 +335,13 @@ public void testAbiExample() { C_INT, C_INT, struct, C_INT, C_INT, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { @@ -348,14 +354,14 @@ public void testAbiExample() { { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, { vmStore(r9, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class) }, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 3); + assertEquals(bindings.nVectorArgs(), 3); } /** @@ -368,24 +374,24 @@ public void testAbiExample() { */ @Test public void testMemoryAddress() { - MethodType mt = MethodType.methodType(void.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test(dataProvider = "structs") @@ -394,20 +400,20 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, expectedBindings, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @@ -426,20 +432,20 @@ public static Object[][] structs() { }, { MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG), new Binding[]{ dup(), - bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), + bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), dup(), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class), - bufferLoad(16, long.class), vmStore(stackStorage(2), long.class) + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class), + bufferLoad(16, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 16), long.class) } }, { MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG, C_LONG), new Binding[]{ dup(), - bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), + bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), dup(), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class), + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class), dup(), - bufferLoad(16, long.class), vmStore(stackStorage(2), long.class), - bufferLoad(24, long.class), vmStore(stackStorage(3), long.class) + bufferLoad(16, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 16), long.class), + bufferLoad(24, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 24), long.class) } }, }; @@ -453,14 +459,14 @@ public void testReturnRegisterStruct() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r11, long.class) }, - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rax, long.class) } }); @@ -474,7 +480,7 @@ public void testReturnRegisterStruct() { bufferStore(8, long.class) }); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -485,20 +491,20 @@ public void testIMR() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class, long.class)); + assertTrue(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, long.class)); assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) } }); checkReturnBindings(callingSequence, new Binding[] {}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -509,8 +515,8 @@ public void testFloatStructsUpcall() { FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, true); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); assertEquals(callingSequence.calleeMethodType(), mt); assertEquals(callingSequence.functionDesc(), fd); @@ -522,7 +528,7 @@ public void testFloatStructsUpcall() { bufferLoad(0, float.class), vmStore(xmm0, float.class) }); - assertEquals(bindings.nVectorArgs, 1); + assertEquals(bindings.nVectorArgs(), 1); } } diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index 0c72d950709..968f3e8db29 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -34,39 +34,46 @@ */ import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.Addressable; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +import jdk.internal.foreign.abi.LinkerOptions; +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; +import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.Win64.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.Binding.copy; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; + import static org.testng.Assert.*; public class TestWindowsCallArranger extends CallArrangerTestBase { + private static final short STACK_SLOT_SIZE = 8; + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) } + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); } @@ -77,13 +84,13 @@ public void testIntegerRegs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { vmStore(r8, int.class) }, @@ -99,13 +106,13 @@ public void testDoubleRegs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -123,21 +130,21 @@ public void testMixed() { C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT, C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, long.class) }, { vmStore(rdx, long.class) }, { vmStore(xmm2, float.class) }, { vmStore(xmm3, float.class) }, - { vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), long.class) }, - { vmStore(stackStorage(2), float.class) }, - { vmStore(stackStorage(3), float.class) } + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), float.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -154,28 +161,28 @@ public void testAbiExample() { C_DOUBLE, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { copy(structLayout), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r8, long.class) }, { vmStore(r9, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), double.class) }, - { vmStore(stackStorage(2), double.class) }, - { vmStore(stackStorage(3), double.class) }, - { vmStore(stackStorage(4), int.class) }, - { vmStore(stackStorage(5), int.class) }, - { vmStore(stackStorage(6), int.class) } + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 32), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 40), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 48), int.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -186,23 +193,23 @@ public void testAbiExampleVarargs() { MethodType mt = MethodType.methodType(void.class, int.class, double.class, int.class, double.class, double.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( - C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE); + C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid( ADDRESS, C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(2))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(xmm1, double.class) }, { vmStore(r8, int.class) }, { dup(), vmStore(r9, double.class), vmStore(xmm3, double.class) }, - { vmStore(stackStorage(0), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), double.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -225,13 +232,13 @@ public void testStructRegister() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { bufferLoad(0, long.class), vmStore(rcx, long.class) } }); @@ -255,16 +262,16 @@ public void testStructReference() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(rcx, long.class) } }); @@ -282,17 +289,17 @@ public void testStructReference() { */ @Test public void testMemoryAddress() { - MethodType mt = MethodType.methodType(void.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -307,13 +314,13 @@ public void testReturnRegisterStruct() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, }); checkReturnBindings(callingSequence, @@ -331,13 +338,13 @@ public void testIMR() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class)); + 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)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -349,10 +356,10 @@ public void testStackStruct() { MemoryLayout struct = MemoryLayout.structLayout(C_POINTER, C_DOUBLE, C_INT); MethodType mt = MethodType.methodType(void.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class); + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( struct, C_INT, C_DOUBLE, C_POINTER, struct, C_INT, C_DOUBLE, C_POINTER, @@ -360,29 +367,29 @@ public void testStackStruct() { struct, C_INT, C_DOUBLE, C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(rcx, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { copy(struct), unboxAddress(), vmStore(rcx, long.class) }, { vmStore(rdx, int.class) }, { vmStore(xmm2, double.class) }, { unboxAddress(), vmStore(r9, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), int.class) }, - { vmStore(stackStorage(2), double.class) }, - { unboxAddress(), vmStore(stackStorage(3), long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(4), long.class) }, - { vmStore(stackStorage(5), int.class) }, - { vmStore(stackStorage(6), double.class) }, - { unboxAddress(), vmStore(stackStorage(7), long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(8), long.class) }, - { vmStore(stackStorage(9), int.class) }, - { vmStore(stackStorage(10), double.class) }, - { unboxAddress(), vmStore(stackStorage(11), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 24), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 32), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 40), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 48), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 56), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 64), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 72), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 80), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 88), long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); diff --git a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java new file mode 100644 index 00000000000..deba982a7cb --- /dev/null +++ b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --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; +import java.lang.foreign.Linker; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.StructLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static java.lang.foreign.MemoryLayout.PathElement.groupElement; +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.assertEquals; + +public class TestCaptureCallState extends NativeTestHelper { + + static { + System.loadLibrary("CaptureCallState"); + if (IS_WINDOWS) { + String system32 = System.getenv("SystemRoot") + "\\system32"; + System.load(system32 + "\\Kernel32.dll"); + System.load(system32 + "\\Ws2_32.dll"); + } + } + + private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, Consumer resultCheck) {} + + @Test(dataProvider = "cases") + public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { + Linker.Option.CaptureCallState stl = Linker.Option.captureCallState(testCase.threadLocalName()); + MethodHandle handle = downcallHandle(testCase.nativeTarget(), testCase.nativeDesc(), stl); + + VarHandle errnoHandle = stl.layout().varHandle(groupElement(testCase.threadLocalName())); + + try (Arena arena = Arena.openConfined()) { + MemorySegment saveSeg = arena.allocate(stl.layout()); + int testValue = 42; + boolean needsAllocator = testCase.nativeDesc().returnLayout().map(StructLayout.class::isInstance).orElse(false); + Object result = needsAllocator + ? handle.invoke(arena, saveSeg, testValue) + : handle.invoke(saveSeg, testValue); + testCase.resultCheck().accept(result); + int savedErrno = (int) errnoHandle.get(saveSeg); + assertEquals(savedErrno, testValue); + } + } + + @DataProvider + public static Object[][] cases() { + List cases = new ArrayList<>(); + + cases.add(new SaveValuesCase("set_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), "errno", o -> {})); + cases.add(new SaveValuesCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), "errno", o -> assertEquals((int) o, 42))); + cases.add(new SaveValuesCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), "errno", o -> assertEquals((double) o, 42.0))); + + cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L))); + cases.add(structCase("SLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L))); + cases.add(structCase("SLLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L, + JAVA_LONG.withName("z"), 42L))); + cases.add(structCase("SD", Map.of(JAVA_DOUBLE.withName("x"), 42D))); + cases.add(structCase("SDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D))); + cases.add(structCase("SDDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D, + JAVA_DOUBLE.withName("z"), 42D))); + + if (IS_WINDOWS) { + cases.add(new SaveValuesCase("SetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "GetLastError", o -> {})); + cases.add(new SaveValuesCase("WSASetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "WSAGetLastError", o -> {})); + } + + return cases.stream().map(tc -> new Object[] {tc}).toArray(Object[][]::new); + } + + static SaveValuesCase structCase(String name, Map fields) { + StructLayout layout = MemoryLayout.structLayout(fields.keySet().toArray(MemoryLayout[]::new)); + + Consumer check = o -> {}; + for (var field : fields.entrySet()) { + 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), value)); + } + + return new SaveValuesCase("set_errno_" + name, FunctionDescriptor.of(layout, JAVA_INT), "errno", check); + } + +} + diff --git a/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c new file mode 100644 index 00000000000..9a8925474a2 --- /dev/null +++ b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 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. + */ + +#include + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void set_errno_V(int value) { + errno = value; +} + +EXPORT int set_errno_I(int value) { + errno = value; + return 42; +} + +EXPORT double set_errno_D(int value) { + errno = value; + return 42.0; +} + +struct SL { + long long x; +}; + +EXPORT struct SL set_errno_SL(int value) { + errno = value; + struct SL s; + s.x = 42; + return s; +} + +struct SLL { + long long x; + long long y; +}; + +EXPORT struct SLL set_errno_SLL(int value) { + errno = value; + struct SLL s; + s.x = 42; + s.y = 42; + return s; +} + +struct SLLL { + long long x; + long long y; + long long z; +}; + +EXPORT struct SLLL set_errno_SLLL(int value) { + errno = value; + struct SLLL s; + s.x = 42; + s.y = 42; + s.z = 42; + return s; +} + +struct SD { + double x; +}; + +EXPORT struct SD set_errno_SD(int value) { + errno = value; + struct SD s; + s.x = 42.0; + return s; +} + +struct SDD { + double x; + double y; +}; + +EXPORT struct SDD set_errno_SDD(int value) { + errno = value; + struct SDD s; + s.x = 42.0; + s.y = 42.0; + return s; +} + +struct SDDD { + double x; + double y; + double z; +}; + +EXPORT struct SDDD set_errno_SDDD(int value) { + errno = value; + struct SDDD s; + s.x = 42.0; + s.y = 42.0; + s.z = 42.0; + return s; +} diff --git a/test/jdk/java/foreign/channels/AbstractChannelsTest.java b/test/jdk/java/foreign/channels/AbstractChannelsTest.java index 1fae62d353e..d3c96bba986 100644 --- a/test/jdk/java/foreign/channels/AbstractChannelsTest.java +++ b/test/jdk/java/foreign/channels/AbstractChannelsTest.java @@ -22,8 +22,9 @@ */ import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; @@ -51,11 +52,6 @@ interface ThrowingConsumer { void accept(T action) throws X; } - static MemorySession closeableSessionOrNull(MemorySession session) { - return (session.isCloseable()) ? - session : null; - } - static long remaining(ByteBuffer[] buffers) { return Arrays.stream(buffers).mapToLong(ByteBuffer::remaining).sum(); } @@ -72,7 +68,7 @@ static ByteBuffer[] clear(ByteBuffer[] buffers) { static final Random RANDOM = RandomFactory.getRandom(); - static ByteBuffer segmentBufferOfSize(MemorySession session, int size) { + static ByteBuffer segmentBufferOfSize(SegmentScope session, int size) { var segment = MemorySegment.allocateNative(size, 1, session); for (int i = 0; i < size; i++) { segment.set(JAVA_BYTE, i, ((byte)RANDOM.nextInt())); @@ -80,7 +76,7 @@ static ByteBuffer segmentBufferOfSize(MemorySession session, int size) { return segment.asByteBuffer(); } - static ByteBuffer[] segmentBuffersOfSize(int len, MemorySession session, int size) { + static ByteBuffer[] segmentBuffersOfSize(int len, SegmentScope session, int size) { ByteBuffer[] bufs = new ByteBuffer[len]; for (int i = 0; i < len; i++) bufs[i] = segmentBufferOfSize(session, size); @@ -92,7 +88,7 @@ static ByteBuffer[] segmentBuffersOfSize(int len, MemorySession session, int siz * where heap can be from the global session or session-less, and direct are * associated with the given session. */ - static ByteBuffer[] mixedBuffersOfSize(int len, MemorySession session, int size) { + static ByteBuffer[] mixedBuffersOfSize(int len, SegmentScope session, int size) { ByteBuffer[] bufs; boolean atLeastOneSessionBuffer = false; do { @@ -125,75 +121,50 @@ static void assertCauses(Throwable ex, Class... exceptions) } } - @DataProvider(name = "confinedSessions") - public static Object[][] confinedSessions() { + @DataProvider(name = "confinedArenas") + public static Object[][] confinedArenas() { return new Object[][] { - { SessionSupplier.NEW_CONFINED }, + { ArenaSupplier.NEW_CONFINED }, }; } - @DataProvider(name = "sharedSessions") - public static Object[][] sharedSessions() { - return new Object[][] { - { SessionSupplier.NEW_SHARED }, - }; - } - - @DataProvider(name = "closeableSessions") - public static Object[][] closeableSessions() { - return Stream.of(sharedSessions(), confinedSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - @DataProvider(name = "implicitSessions") - public static Object[][] implicitSessions() { + @DataProvider(name = "sharedArenas") + public static Object[][] sharedArenas() { return new Object[][] { - { SessionSupplier.GLOBAL }, + { ArenaSupplier.NEW_SHARED }, }; } - @DataProvider(name = "sharedAndImplicitSessions") - public static Object[][] sharedAndImplicitSessions() { - return Stream.of(sharedSessions(), implicitSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - @DataProvider(name = "allSessions") - public static Object[][] allSessions() { - return Stream.of(implicitSessions(), closeableSessions()) + @DataProvider(name = "closeableArenas") + public static Object[][] closeableArenas() { + return Stream.of(sharedArenas(), confinedArenas()) .flatMap(Arrays::stream) .toArray(Object[][]::new); } - @DataProvider(name = "sharedSessionsAndTimeouts") - public static Object[][] sharedSessionsAndTimeouts() { + @DataProvider(name = "sharedArenasAndTimeouts") + public static Object[][] sharedArenasAndTimeouts() { return new Object[][] { - { SessionSupplier.NEW_SHARED , 0 }, - { SessionSupplier.NEW_SHARED , 30 }, + { ArenaSupplier.NEW_SHARED , 0 }, + { ArenaSupplier.NEW_SHARED , 30 }, }; } - static class SessionSupplier implements Supplier { + static class ArenaSupplier implements Supplier { - static final Supplier NEW_CONFINED = - new SessionSupplier(MemorySession::openConfined, "newConfinedSession()"); - static final Supplier NEW_SHARED = - new SessionSupplier(MemorySession::openShared, "newSharedSession()"); - static final Supplier NEW_IMPLICIT = - new SessionSupplier(MemorySession::openImplicit, "newImplicitSession()"); - static final Supplier GLOBAL = - new SessionSupplier(MemorySession::global, "globalSession()"); + static final Supplier NEW_CONFINED = + new ArenaSupplier(Arena::openConfined, "confined arena"); + static final Supplier NEW_SHARED = + new ArenaSupplier(Arena::openShared, "shared arena"); - private final Supplier supplier; + private final Supplier supplier; private final String str; - private SessionSupplier(Supplier supplier, String str) { + private ArenaSupplier(Supplier supplier, String str) { this.supplier = supplier; this.str = str; } @Override public String toString() { return str; } - @Override public MemorySession get() { return supplier.get(); } + @Override public Arena get() { return supplier.get(); } } } diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 9278c7748a7..3091514cc58 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -33,8 +33,8 @@ */ import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.StandardSocketOptions; @@ -67,15 +67,15 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; /** Tests that confined sessions are not supported. */ - @Test(dataProvider = "confinedSessions") - public void testWithConfined(Supplier sessionSupplier) + @Test(dataProvider = "confinedArenas") + public void testWithConfined(Supplier arenaSupplier) throws Throwable { try (var channel = AsynchronousSocketChannel.open(); var server = AsynchronousServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); var bb = segment.asByteBuffer(); var bba = new ByteBuffer[] { bb }; List> ioOps = List.of( @@ -100,17 +100,17 @@ public void testWithConfined(Supplier sessionSupplier) } /** Tests that I/O with a closed session throws a suitable exception. */ - @Test(dataProvider = "sharedSessionsAndTimeouts") - public void testIOWithClosedSharedSession(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testIOWithClosedSharedSession(Supplier arenaSupplier, int timeout) throws Exception { try (var channel = AsynchronousSocketChannel.open(); var server = AsynchronousServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = sessionSupplier.get(); - ByteBuffer bb = segmentBufferOfSize(session, 64); - ByteBuffer[] buffers = segmentBuffersOfSize(8, session, 32); - ((MemorySession)session).close(); + Arena drop = arenaSupplier.get(); + ByteBuffer bb = segmentBufferOfSize(drop.scope(), 64); + ByteBuffer[] buffers = segmentBuffersOfSize(8, drop.scope(), 32); + drop.close(); { assertCauses(expectThrows(EE, () -> connectedChannel.read(bb).get()), IOE, ISE); } @@ -151,17 +151,17 @@ public void testIOWithClosedSharedSession(Supplier sessionSupplie } /** Tests basic I/O operations work with views over implicit and shared sessions. */ - @Test(dataProvider = "sharedAndImplicitSessions") - public void testBasicIOWithSupportedSession(Supplier sessionSupplier) + @Test(dataProvider = "sharedArenas") + public void testBasicIOWithSupportedSession(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment1 = MemorySegment.allocateNative(10, 1, session); - MemorySegment segment2 = MemorySegment.allocateNative(10, 1, session); + var scp = drop = arenaSupplier.get()) { + MemorySegment segment1 = MemorySegment.allocateNative(10, 1, drop.scope()); + MemorySegment segment2 = MemorySegment.allocateNative(10, 1, drop.scope()); for (int i = 0; i < 10; i++) { segment1.set(JAVA_BYTE, i, (byte) i); } @@ -184,8 +184,8 @@ public void testBasicIOWithSupportedSession(Supplier sessionSuppl assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); } { // Gathering/Scattering variants - var writeBuffers = mixedBuffersOfSize(16, session, 32); - var readBuffers = mixedBuffersOfSize(16, session, 32); + var writeBuffers = mixedBuffersOfSize(16, drop.scope(), 32); + var readBuffers = mixedBuffersOfSize(16, drop.scope(), 32); long expectedCount = remaining(writeBuffers); var writeHandler = new TestHandler(); asc1.write(writeBuffers, 0, 16, 30L, SECONDS, null, writeHandler); @@ -199,15 +199,15 @@ public void testBasicIOWithSupportedSession(Supplier sessionSuppl } /** Tests that a session is not closeable when there is an outstanding read operation. */ - @Test(dataProvider = "sharedSessionsAndTimeouts") - public void testCloseWithOutstandingRead(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testCloseWithOutstandingRead(Supplier arenaSupplier, int timeout) throws Throwable { try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); var bb = segment.asByteBuffer(); var bba = new ByteBuffer[] { bb }; List> readOps = List.of( @@ -221,28 +221,28 @@ public void testCloseWithOutstandingRead(Supplier sessionSupplier var handler = new TestHandler(); ioOp.accept(handler); assertFalse(handler.isDone()); - assertTrue(session.isAlive()); - assertMessage(expectThrows(ISE, () -> session.close()), "Session is acquired by"); + assertTrue(drop.scope().isAlive()); + assertMessage(expectThrows(ISE, () -> drop.close()), "Session is acquired by"); // write to allow the blocking read complete, which will // in turn unlock the session and allow it to be closed. asc2.write(ByteBuffer.wrap(new byte[] { 0x01 })).get(); handler.await().assertCompleteWith(1L); - assertTrue(session.isAlive()); + assertTrue(drop.scope().isAlive()); } } } /** 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 = "sharedSessionsAndTimeouts") - public void testCloseWithOutstandingWrite(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testCloseWithOutstandingWrite(Supplier arenaSupplier, int timeout) throws Throwable { try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var session = closeableSessionOrNull(sessionSupplier.get())) { + var drop = arenaSupplier.get()) { // number of bytes written final AtomicLong bytesWritten = new AtomicLong(0); @@ -252,7 +252,7 @@ public void testCloseWithOutstandingWrite(Supplier sessionSupplie // write until socket buffer is full so as to create the conditions // for when a write does not complete immediately - var bba = segmentBuffersOfSize(32, session, 128); + var bba = segmentBuffersOfSize(32, drop.scope(), 128); TestHandler handler; outstandingWriteOps.getAndIncrement(); asc1.write(bba, 0, bba.length, timeout, SECONDS, null, @@ -261,7 +261,7 @@ public void completed(Long result, Void att) { super.completed(result, att); bytesWritten.addAndGet(result); if (continueWriting.get()) { - var bba = segmentBuffersOfSize(32, session, 128); + var bba = segmentBuffersOfSize(32, drop.scope(), 128); outstandingWriteOps.getAndIncrement(); asc1.write(bba, 0, bba.length, timeout, SECONDS, null, this); } @@ -271,8 +271,8 @@ public void completed(Long result, Void att) { // give time for socket buffer to fill up. awaitNoFurtherWrites(bytesWritten); - assertMessage(expectThrows(ISE, () -> session.close()), "Session is acquired by"); - assertTrue(session.isAlive()); + assertMessage(expectThrows(ISE, () -> drop.close()), "Session is acquired by"); + assertTrue(drop.scope().isAlive()); // signal handler to stop further writing continueWriting.set(false); @@ -280,7 +280,7 @@ public void completed(Long result, Void att) { // read to allow the outstanding write complete, which will // in turn unlock the session and allow it to be closed. readNBytes(asc2, bytesWritten.get()); - assertTrue(session.isAlive()); + assertTrue(drop.scope().isAlive()); awaitOutstandingWrites(outstandingWriteOps); handler.await(); } diff --git a/test/jdk/java/foreign/channels/TestSocketChannels.java b/test/jdk/java/foreign/channels/TestSocketChannels.java index 4b4aa91c886..98cc84e0bf7 100644 --- a/test/jdk/java/foreign/channels/TestSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestSocketChannels.java @@ -30,6 +30,7 @@ * @run testng/othervm TestSocketChannels */ +import java.lang.foreign.Arena; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; @@ -42,7 +43,7 @@ import java.util.stream.Stream; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; @@ -56,16 +57,16 @@ public class TestSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; static final Class WTE = WrongThreadException.class; - @Test(dataProvider = "closeableSessions") - public void testBasicIOWithClosedSegment(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIOWithClosedSegment(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = sessionSupplier.get(); - ByteBuffer bb = segmentBufferOfSize(session, 16); - ((MemorySession)session).close(); + Arena drop = arenaSupplier.get(); + ByteBuffer bb = segmentBufferOfSize(drop.scope(), 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"); @@ -75,16 +76,16 @@ public void testBasicIOWithClosedSegment(Supplier sessionSupplier } } - @Test(dataProvider = "closeableSessions") - public void testScatterGatherWithClosedSegment(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testScatterGatherWithClosedSegment(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = (MemorySession)sessionSupplier.get(); - ByteBuffer[] buffers = segmentBuffersOfSize(8, session, 16); - session.close(); + Arena drop = arenaSupplier.get(); + ByteBuffer[] buffers = segmentBuffersOfSize(8, drop.scope(), 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"); @@ -92,17 +93,17 @@ public void testScatterGatherWithClosedSegment(Supplier sessionSu } } - @Test(dataProvider = "allSessions") - public void testBasicIO(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIO(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment1 = MemorySegment.allocateNative(10, 1, session); - MemorySegment segment2 = MemorySegment.allocateNative(10, 1, session); + var scp = drop = arenaSupplier.get()) { + MemorySegment segment1 = MemorySegment.allocateNative(10, 1, drop.scope()); + MemorySegment segment2 = MemorySegment.allocateNative(10, 1, drop.scope()); for (int i = 0; i < 10; i++) { segment1.set(JAVA_BYTE, i, (byte) i); } @@ -132,15 +133,15 @@ public void testBasicHeapIOWithGlobalSession() throws Exception { } } - @Test(dataProvider = "confinedSessions") - public void testIOOnConfinedFromAnotherThread(Supplier sessionSupplier) + @Test(dataProvider = "confinedArenas") + public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connected = connectChannels(server, channel); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); ByteBuffer bb = segment.asByteBuffer(); List ioOps = List.of( () -> channel.write(bb), @@ -161,17 +162,17 @@ public void testIOOnConfinedFromAnotherThread(Supplier sessionSup } } - @Test(dataProvider = "allSessions") - public void testScatterGatherIO(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testScatterGatherIO(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - var writeBuffers = mixedBuffersOfSize(32, session, 64); - var readBuffers = mixedBuffersOfSize(32, session, 64); + var scp = drop = arenaSupplier.get()) { + var writeBuffers = mixedBuffersOfSize(32, drop.scope(), 64); + var readBuffers = mixedBuffersOfSize(32, drop.scope(), 64); long expectedCount = remaining(writeBuffers); assertEquals(writeNBytes(sc1, writeBuffers, 0, 32, expectedCount), expectedCount); assertEquals(readNBytes(sc2, readBuffers, 0, 32, expectedCount), expectedCount); @@ -179,19 +180,19 @@ public void testScatterGatherIO(Supplier sessionSupplier) } } - @Test(dataProvider = "closeableSessions") - public void testBasicIOWithDifferentSessions(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIOWithDifferentSessions(Supplier arenaSupplier) throws Exception { try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var session1 = closeableSessionOrNull(sessionSupplier.get()); - var session2 = closeableSessionOrNull(sessionSupplier.get())) { - var writeBuffers = Stream.of(mixedBuffersOfSize(16, session1, 64), mixedBuffersOfSize(16, session2, 64)) + var drop1 = arenaSupplier.get(); + var drop2 = arenaSupplier.get()) { + var writeBuffers = Stream.of(mixedBuffersOfSize(16, drop1.scope(), 64), mixedBuffersOfSize(16, drop2.scope(), 64)) .flatMap(Arrays::stream) .toArray(ByteBuffer[]::new); - var readBuffers = Stream.of(mixedBuffersOfSize(16, session1, 64), mixedBuffersOfSize(16, session2, 64)) + var readBuffers = Stream.of(mixedBuffersOfSize(16, drop1.scope(), 64), mixedBuffersOfSize(16, drop2.scope(), 64)) .flatMap(Arrays::stream) .toArray(ByteBuffer[]::new); diff --git a/test/jdk/java/foreign/dontrelease/TestDontRelease.java b/test/jdk/java/foreign/dontrelease/TestDontRelease.java new file mode 100644 index 00000000000..1d8ca974c90 --- /dev/null +++ b/test/jdk/java/foreign/dontrelease/TestDontRelease.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestDontRelease + */ + +import org.testng.annotations.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static org.testng.Assert.assertTrue; + +public class TestDontRelease extends NativeTestHelper { + + static { + System.loadLibrary("DontRelease"); + } + + @Test + public void testDontRelease() { + MethodHandle handle = downcallHandle("test_ptr", FunctionDescriptor.ofVoid(ADDRESS)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(JAVA_INT); + arena.scope().whileAlive(() -> { + Thread t = new Thread(() -> { + try { + // acquire of the segment should fail here, + // due to wrong thread + handle.invokeExact(segment); + } catch (Throwable e) { + // catch the exception. + assertTrue(e instanceof WrongThreadException); + assertTrue(e.getMessage().matches(".*Attempted access outside owning thread.*")); + } + }); + t.start(); + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // the downcall above should not have called release on the session + // so doing it here should succeed without error + }); + } + } +} + diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java b/test/jdk/java/foreign/dontrelease/libDontRelease.c similarity index 83% rename from test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java rename to test/jdk/java/foreign/dontrelease/libDontRelease.c index c3d26a5bdd8..c7a8f743083 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java +++ b/test/jdk/java/foreign/dontrelease/libDontRelease.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -21,8 +21,10 @@ * questions. */ -package org.reactivestreams.tck.flow.support; +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif -public interface Function { - public Out apply(In in) throws Throwable; -} +EXPORT void test_ptr(void* ptr) {} diff --git a/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java b/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java new file mode 100644 index 00000000000..c76cdfdbe86 --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 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. + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.lang.Module; +import java.lang.ModuleLayer; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; + +// This class creates a dynamic module layer and loads the +// panama_module in it. enableNativeAccess on that dynamic +// module is called depending on the command line option. +// +// Usage: +// java --enable-native-access=ALL-UNNAMED NativeAccessDynamicMain [main-args] +public class NativeAccessDynamicMain { + public static void main(String[] args) throws Exception { + String modulePath = args[0]; + String moduleAndClsName = args[1]; + boolean enableNativeAccess = Boolean.parseBoolean(args[2]); + String[] mainArgs = args.length > 2? Arrays.copyOfRange(args, 3, args.length) : new String[0]; + + int idx = moduleAndClsName.indexOf('/'); + String moduleName = moduleAndClsName.substring(0, idx); + String className = moduleAndClsName.substring(idx+1); + + Path[] paths = Stream.of(modulePath.split(File.pathSeparator)) + .map(Paths::get) + .toArray(Path[]::new); + ModuleFinder mf = ModuleFinder.of(paths); + var mrefs = mf.findAll(); + if (mrefs.isEmpty()) { + throw new RuntimeException("No modules module path: " + modulePath); + } + + var rootMods = mrefs.stream(). + map(mr->mr.descriptor().name()). + collect(Collectors.toSet()); + + ModuleLayer boot = ModuleLayer.boot(); + var conf = boot.configuration(). + resolve(mf, ModuleFinder.of(), rootMods); + String firstMod = rootMods.iterator().next(); + URLClassLoader cl = new URLClassLoader(new URL[] { paths[0].toFile().toURL() }); + ModuleLayer.Controller controller = boot.defineModulesWithOneLoader(conf, List.of(boot), cl); + ModuleLayer layer = controller.layer(); + Module mod = layer.findModule(firstMod).get(); + + // conditionally grant native access to the dynamic module created + if (enableNativeAccess) { + controller.enableNativeAccess(mod); + } + Class mainCls = Class.forName(mod, className); + var main = mainCls.getMethod("main", String[].class); + main.invoke(null, (Object)mainArgs); + } +} diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java new file mode 100644 index 00000000000..6be989ec1ac --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @requires !vm.musl + * + * @library /test/lib + * @build TestEnableNativeAccessDynamic + * panama_module/* + NativeAccessDynamicMain + * @run testng/othervm/timeout=180 TestEnableNativeAccessDynamic + * @summary Test for dynamically setting --enable-native-access flag for a module + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +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.*; + +@Test +public class TestEnableNativeAccessDynamic { + + static final String MODULE_PATH = System.getProperty("jdk.module.path"); + + static final String PANAMA_MAIN = "panama_module/org.openjdk.foreigntest.PanamaMainDirect"; + static final String PANAMA_REFLECTION = "panama_module/org.openjdk.foreigntest.PanamaMainReflection"; + static final String PANAMA_INVOKE = "panama_module/org.openjdk.foreigntest.PanamaMainInvoke"; + static final String PANAMA_JNI = "panama_module/org.openjdk.foreigntest.PanamaMainJNI"; + + /** + * Represents the expected result of a test. + */ + static final class Result { + private final boolean success; + private final List expectedOutput = new ArrayList<>(); + private final List notExpectedOutput = new ArrayList<>(); + + Result(boolean success) { + this.success = success; + } + + Result expect(String msg) { + expectedOutput.add(msg); + return this; + } + + Result doNotExpect(String msg) { + notExpectedOutput.add(msg); + return this; + } + + boolean shouldSucceed() { + return success; + } + + Stream expectedOutput() { + return expectedOutput.stream(); + } + + Stream notExpectedOutput() { + return notExpectedOutput.stream(); + } + + @Override + public String toString() { + String s = (success) ? "success" : "failure"; + for (String msg : expectedOutput) { + s += "/" + msg; + } + return s; + } + } + + static Result success() { + return new Result(true); + } + + static Result successNoWarning() { + return success().doNotExpect("WARNING"); + } + + static Result failWithError(String expectedOutput) { + return new Result(false).expect(expectedOutput); + } + + @DataProvider(name = "succeedCases") + public Object[][] succeedCases() { + return new Object[][] { + { "panama_enable_native_access", PANAMA_MAIN, successNoWarning() }, + { "panama_enable_native_access_reflection", PANAMA_REFLECTION, successNoWarning() }, + { "panama_enable_native_access_invoke", PANAMA_INVOKE, successNoWarning() }, + }; + } + + @DataProvider(name = "failureCases") + public Object[][] failureCases() { + String errMsg = "Illegal native access from: module panama_module"; + return new Object[][] { + { "panama_enable_native_access_fail", PANAMA_MAIN, failWithError(errMsg) }, + { "panama_enable_native_access_fail_reflection", PANAMA_REFLECTION, failWithError(errMsg) }, + { "panama_enable_native_access_fail_invoke", PANAMA_INVOKE, failWithError(errMsg) }, + }; + } + + /** + * Checks an expected result with the output captured by the given + * OutputAnalyzer. + */ + void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { + expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); + expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); + int exitValue = outputAnalyzer.getExitValue(); + if (expectedResult.shouldSucceed()) { + assertTrue(exitValue == 0); + } else { + assertTrue(exitValue != 0); + } + } + + /** + * Runs the test to execute the given test action. The VM is run with the + * given VM options and the output checked to see that it matches the + * expected result. + */ + OutputAnalyzer run(String action, String moduleAndCls, boolean enableNativeAccess, + Result expectedResult, boolean panamaModuleInBootLayer) throws Exception + { + List list = new ArrayList<>(); + list.add("--enable-preview"); + if (panamaModuleInBootLayer) { + list.addAll(List.of("-p", MODULE_PATH)); + list.add("--add-modules=panama_module"); + list.add("--enable-native-access=panama_module"); + } else { + list.add("--enable-native-access=ALL-UNNAMED"); + } + list.addAll(List.of("NativeAccessDynamicMain", MODULE_PATH, + moduleAndCls, Boolean.toString(enableNativeAccess), action)); + String[] opts = list.toArray(String[]::new); + OutputAnalyzer outputAnalyzer = ProcessTools + .executeTestJava(opts) + .outputTo(System.out) + .errorTo(System.out); + checkResult(expectedResult, outputAnalyzer); + return outputAnalyzer; + } + + @Test(dataProvider = "succeedCases") + public void testSucceed(String action, String moduleAndCls, + Result expectedResult) throws Exception { + run(action, moduleAndCls, true, expectedResult, false); + } + + @Test(dataProvider = "failureCases") + public void testFailures(String action, String moduleAndCls, + Result expectedResult) throws Exception { + run(action, moduleAndCls, false, expectedResult, false); + } + + // make sure that having a same named module in boot layer with native access + // does not influence same named dynamic module. + @Test(dataProvider = "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/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java index e042a773fda..3743ac73835 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; public class PanamaMainDirect { public static void main(String[] args) { @@ -39,7 +40,7 @@ public static void testDirectAccessCLinker() { public static void testDirectAccessMemorySegment() { System.out.println("Trying to get MemorySegment"); - MemorySegment.ofAddress(MemoryAddress.NULL, 4000, MemorySession.global()); + MemorySegment.ofAddress(0, 4000, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java index b50ebe9ca80..0d4d7bb4bb0 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.*; public class PanamaMainInvoke { @@ -43,8 +44,8 @@ public static void testInvokenativeLinker() throws Throwable { public static void testInvokeMemorySegment() throws Throwable { System.out.println("Trying to get MemorySegment"); var mh = MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", - MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, MemorySession.class)); - var seg = (MemorySegment)mh.invokeExact(MemoryAddress.NULL, 4000L, MemorySession.global()); + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)); + var seg = (MemorySegment)mh.invokeExact(0L, 4000L, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java index 7a8eab027e9..68aebc73ab5 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.reflect.Method; public class PanamaMainReflection { @@ -41,8 +42,8 @@ public static void testReflectionnativeLinker() throws Throwable { public static void testReflectionMemorySegment() throws Throwable { System.out.println("Trying to get MemorySegment"); - Method method = MemorySegment.class.getDeclaredMethod("ofAddress", MemoryAddress.class, long.class, MemorySession.class); - method.invoke(null, MemoryAddress.NULL, 4000L, MemorySession.global()); + Method method = MemorySegment.class.getDeclaredMethod("ofAddress", long.class, long.class, SegmentScope.class); + method.invoke(null, 0L, 4000L, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java index 319fcde6600..090a57bcc7b 100644 --- a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java +++ b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java @@ -23,13 +23,11 @@ package handle.invoker; -import java.lang.foreign.Addressable; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; @@ -71,11 +69,10 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(MethodHandle.class, MethodHandles.identity(int.class)); addDefaultMapping(Charset.class, Charset.defaultCharset()); addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); - addDefaultMapping(MemoryAddress.class, MemoryAddress.NULL); - addDefaultMapping(Addressable.class, MemoryAddress.NULL); + addDefaultMapping(MemorySegment.class, MemorySegment.NULL); addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(FunctionDescriptor.class, FunctionDescriptor.ofVoid()); - addDefaultMapping(MemorySession.class, MemorySession.openImplicit()); + addDefaultMapping(SegmentScope.class, SegmentScope.auto()); addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); addDefaultMapping(ValueLayout.OfByte.class, ValueLayout.JAVA_BYTE); addDefaultMapping(ValueLayout.OfBoolean.class, ValueLayout.JAVA_BOOLEAN); 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 f3f5c6238e9..62014baf8af 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 @@ -23,19 +23,15 @@ package handle.lookup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SymbolLookup; -import java.lang.foreign.VaList; -import java.lang.foreign.ValueLayout; import java.nio.file.Path; @@ -54,120 +50,21 @@ static Object[][] restrictedMethods() { return new Object[][]{ { MethodHandles.lookup().findStatic(Linker.class, "nativeLinker", MethodType.methodType(Linker.class)), "Linker::nativeLinker" }, - { MethodHandles.lookup().findStatic(VaList.class, "ofAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, MemorySession.class)), - "VaList::ofAddress/1" }, { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", - MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, MemorySession.class)), - "MemorySegment::ofAddress" }, + MethodType.methodType(MemorySegment.class, long.class, long.class)), + "MemorySegment::ofAddress/2" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)), + "MemorySegment::ofAddress/3" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class, Runnable.class)), + "MemorySegment::ofAddress/4" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", - MethodType.methodType(SymbolLookup.class, String.class, MemorySession.class)), + MethodType.methodType(SymbolLookup.class, String.class, SegmentScope.class)), "SymbolLookup::libraryLookup(String)" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", - MethodType.methodType(SymbolLookup.class, Path.class, MemorySession.class)), + MethodType.methodType(SymbolLookup.class, Path.class, SegmentScope.class)), "SymbolLookup::libraryLookup(Path)" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getUtf8String", - MethodType.methodType(String.class, long.class)), - "MemoryAddress::getUtf8String" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setUtf8String", - MethodType.methodType(void.class, long.class, String.class)), - "MemoryAddress::setUtf8String" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(byte.class, ValueLayout.OfByte.class, long.class)), - "MemoryAddress::get/byte" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(boolean.class, ValueLayout.OfBoolean.class, long.class)), - "MemoryAddress::get/boolean" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(char.class, ValueLayout.OfChar.class, long.class)), - "MemoryAddress::get/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(short.class, ValueLayout.OfShort.class, long.class)), - "MemoryAddress::get/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(int.class, ValueLayout.OfInt.class, long.class)), - "MemoryAddress::get/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(float.class, ValueLayout.OfFloat.class, long.class)), - "MemoryAddress::get/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(long.class, ValueLayout.OfLong.class, long.class)), - "MemoryAddress::get/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(double.class, ValueLayout.OfDouble.class, long.class)), - "MemoryAddress::get/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(MemoryAddress.class, ValueLayout.OfAddress.class, long.class)), - "MemoryAddress::get/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfByte.class, long.class, byte.class)), - "MemoryAddress::set/byte" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfBoolean.class, long.class, boolean.class)), - "MemoryAddress::set/boolean" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfChar.class, long.class, char.class)), - "MemoryAddress::set/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfShort.class, long.class, short.class)), - "MemoryAddress::set/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfInt.class, long.class, int.class)), - "MemoryAddress::set/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfFloat.class, long.class, float.class)), - "MemoryAddress::set/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfLong.class, long.class, long.class)), - "MemoryAddress::set/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfDouble.class, long.class, double.class)), - "MemoryAddress::set/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfAddress.class, long.class, Addressable.class)), - "MemoryAddress::set/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(char.class, ValueLayout.OfChar.class, long.class)), - "MemoryAddress::getAtIndex/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(short.class, ValueLayout.OfShort.class, long.class)), - "MemoryAddress::getAtIndex/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(int.class, ValueLayout.OfInt.class, long.class)), - "MemoryAddress::getAtIndex/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(float.class, ValueLayout.OfFloat.class, long.class)), - "MemoryAddress::getAtIndex/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(long.class, ValueLayout.OfLong.class, long.class)), - "MemoryAddress::getAtIndex/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(double.class, ValueLayout.OfDouble.class, long.class)), - "MemoryAddress::getAtIndex/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(MemoryAddress.class, ValueLayout.OfAddress.class, long.class)), - "MemoryAddress::getAtIndex/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfChar.class, long.class, char.class)), - "MemoryAddress::setAtIndex/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfShort.class, long.class, short.class)), - "MemoryAddress::setAtIndex/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfInt.class, long.class, int.class)), - "MemoryAddress::setAtIndex/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfFloat.class, long.class, float.class)), - "MemoryAddress::setAtIndex/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfLong.class, long.class, long.class)), - "MemoryAddress::set/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfDouble.class, long.class, double.class)), - "MemoryAddress::set/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfAddress.class, long.class, Addressable.class)), - "MemoryAddress::set/address" }, }; } catch (Throwable ex) { throw new ExceptionInInitializerError((ex)); diff --git a/src/hotspot/share/metaprogramming/isConst.hpp b/test/jdk/java/foreign/libNull.c similarity index 72% rename from src/hotspot/share/metaprogramming/isConst.hpp rename to test/jdk/java/foreign/libNull.c index 744e9c665ec..52ea8493f21 100644 --- a/src/hotspot/share/metaprogramming/isConst.hpp +++ b/test/jdk/java/foreign/libNull.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -19,15 +19,14 @@ * 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_METAPROGRAMMING_ISCONST_HPP -#define SHARE_METAPROGRAMMING_ISCONST_HPP - -#include "metaprogramming/integralConstant.hpp" +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif -template struct IsConst: public FalseType {}; -template struct IsConst: public TrueType {}; +#include -#endif // SHARE_METAPROGRAMMING_ISCONST_HPP +EXPORT void* get_null() { return NULL; } diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java index aff471cc241..b6a4b82616b 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java @@ -42,11 +42,11 @@ public static void main(String[] args) throws ReflectiveOperationException { ClassLoader loader1 = newClassLoader("lookup"); Class lookup = loader1.loadClass("lookup.Lookup"); Method fooSymbol = lookup.getDeclaredMethod("fooSymbol"); - Addressable foo = (Addressable)fooSymbol.invoke(null); + MemorySegment foo = (MemorySegment) fooSymbol.invoke(null); ClassLoader loader2 = newClassLoader("invoker"); Class invoker = loader2.loadClass("invoker.Invoker"); - Method invoke = invoker.getDeclaredMethod("invoke", Addressable.class); + Method invoke = invoker.getDeclaredMethod("invoke", MemorySegment.class); invoke.invoke(null, foo); loader1 = null; diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java index 1d981722fc0..f5d0a8073a5 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java @@ -42,10 +42,10 @@ public class TestLoaderLookupJNI { @Test void testLoaderLookupJNI() { SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - assertTrue(loaderLookup.lookup("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); + assertTrue(loaderLookup.find("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); // now try calling via JNI loaderLookup = loaderLookup0(); // lookup backed by application loader, so can see same symbols - assertTrue(loaderLookup.lookup("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); + assertTrue(loaderLookup.find("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); } static native SymbolLookup loaderLookup0(); diff --git a/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java index eb188719a98..06bf9eac4a8 100644 --- a/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java +++ b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java @@ -26,7 +26,7 @@ import java.lang.foreign.*; public class Invoker { - public static void invoke(Addressable symbol) throws Throwable { + public static void invoke(MemorySegment symbol) throws Throwable { var linker = Linker.nativeLinker(); var handle = linker.downcallHandle(symbol, FunctionDescriptor.ofVoid()); handle.invokeExact(); diff --git a/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java index 00946f75c20..6efa9e0ac09 100644 --- a/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java +++ b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java @@ -23,7 +23,7 @@ package lookup; -import java.lang.foreign.Addressable; +import java.lang.foreign.MemorySegment; import java.lang.foreign.SymbolLookup; public class Lookup { @@ -31,7 +31,7 @@ public class Lookup { System.loadLibrary("Foo"); } - public static Addressable fooSymbol() { - return SymbolLookup.loaderLookup().lookup("foo").get(); + public static MemorySegment fooSymbol() { + return SymbolLookup.loaderLookup().find("foo").get(); } } diff --git a/test/jdk/java/foreign/normalize/TestNormalize.java b/test/jdk/java/foreign/normalize/TestNormalize.java new file mode 100644 index 00000000000..0ba8ef6d36f --- /dev/null +++ b/test/jdk/java/foreign/normalize/TestNormalize.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @library ../ + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm + * --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.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +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; + +// test normalization of smaller than int primitive types +public class TestNormalize extends NativeTestHelper { + + private static final Linker LINKER = Linker.nativeLinker(); + private static final MethodHandle SAVE_BOOLEAN_AS_INT; + private static final MethodHandle SAVE_BYTE_AS_INT; + private static final MethodHandle SAVE_SHORT_AS_INT; + private static final MethodHandle SAVE_CHAR_AS_INT; + + private static final MethodHandle BOOLEAN_TO_INT; + private static final MethodHandle BYTE_TO_INT; + private static final MethodHandle SHORT_TO_INT; + private static final MethodHandle CHAR_TO_INT; + + private static final MethodHandle NATIVE_BOOLEAN_TO_INT; + + private static final int BOOLEAN_HOB_MASK = ~0b1; + private static final int BYTE_HOB_MASK = ~0xFF; + private static final int SHORT_HOB_MASK = ~0xFFFF; + private static final int CHAR_HOB_MASK = ~0xFFFF; + + private static final MethodHandle SAVE_BOOLEAN; + + static { + System.loadLibrary("Normalize"); + + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + SAVE_BOOLEAN_AS_INT = lookup.findStatic(TestNormalize.class, "saveBooleanAsInt", MethodType.methodType(void.class, boolean.class, int[].class)); + SAVE_BYTE_AS_INT = lookup.findStatic(TestNormalize.class, "saveByteAsInt", MethodType.methodType(void.class, byte.class, int[].class)); + SAVE_SHORT_AS_INT = lookup.findStatic(TestNormalize.class, "saveShortAsInt", MethodType.methodType(void.class, short.class, int[].class)); + SAVE_CHAR_AS_INT = lookup.findStatic(TestNormalize.class, "saveCharAsInt", MethodType.methodType(void.class, char.class, int[].class)); + + BOOLEAN_TO_INT = lookup.findStatic(TestNormalize.class, "booleanToInt", MethodType.methodType(int.class, boolean.class)); + BYTE_TO_INT = lookup.findStatic(TestNormalize.class, "byteToInt", MethodType.methodType(int.class, byte.class)); + SHORT_TO_INT = lookup.findStatic(TestNormalize.class, "shortToInt", MethodType.methodType(int.class, short.class)); + CHAR_TO_INT = lookup.findStatic(TestNormalize.class, "charToInt", MethodType.methodType(int.class, char.class)); + + NATIVE_BOOLEAN_TO_INT = LINKER.downcallHandle(findNativeOrThrow("int_identity"), FunctionDescriptor.of(JAVA_INT, JAVA_BOOLEAN)); + + SAVE_BOOLEAN = lookup.findStatic(TestNormalize.class, "saveBoolean", MethodType.methodType(void.class, boolean.class, boolean[].class)); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + + // The idea of this test is that we pass a 'dirty' int value down to native code, and then receive it back + // as the argument to an upcall, as well as the result of the downcall, but with a sub-int type (boolean, byte, short, char). + // 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") + 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); + // use actual type as return type to test downcall return normalization + FunctionDescriptor downcallDesc = FunctionDescriptor.of(layout, ADDRESS, JAVA_INT); + + MemorySegment target = findNativeOrThrow("test"); + MethodHandle downcallHandle = LINKER.downcallHandle(target, downcallDesc); + downcallHandle = MethodHandles.filterReturnValue(downcallHandle, toInt); + + try (Arena arena = Arena.openConfined()) { + int[] box = new int[1]; + saver = MethodHandles.insertArguments(saver, 1, box); + MemorySegment upcallStub = LINKER.upcallStub(saver, upcallDesc, arena.scope()); + int dirtyValue = testValue | hobMask; // set all bits that should not be set + + // test after JIT as well + for (int i = 0; i < 20_000; i++) { + doCall(downcallHandle, upcallStub, box, dirtyValue, hobMask); + } + } + } + + 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 + } + + public static void saveBooleanAsInt(boolean b, int[] box) { + box[0] = booleanToInt(b); + } + public static void saveByteAsInt(byte b, int[] box) { + box[0] = byteToInt(b); + } + public static void saveShortAsInt(short s, int[] box) { + box[0] = shortToInt(s); + } + public static void saveCharAsInt(char c, int[] box) { + box[0] = charToInt(c); + } + + public static int booleanToInt(boolean b) { + try { + return (int) NATIVE_BOOLEAN_TO_INT.invokeExact(b); // FIXME do in pure Java? + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + public static int byteToInt(byte b) { + return b; + } + public static int charToInt(char c) { + return c; + } + 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 }, + { JAVA_BYTE, byteToInt((byte) 42), BYTE_HOB_MASK, BYTE_TO_INT, SAVE_BYTE_AS_INT }, + { JAVA_SHORT, shortToInt((short) 42), SHORT_HOB_MASK, SHORT_TO_INT, SAVE_SHORT_AS_INT }, + { JAVA_CHAR, charToInt('a'), CHAR_HOB_MASK, CHAR_TO_INT, SAVE_CHAR_AS_INT } + }; + } + + // 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") + 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)); + + boolean[] box = new boolean[1]; + MethodHandle upcallTarget = MethodHandles.insertArguments(SAVE_BOOLEAN, 1, box); + + try (Arena arena = Arena.openConfined()) { + MemorySegment callback = LINKER.upcallStub(upcallTarget, FunctionDescriptor.ofVoid(JAVA_BOOLEAN), arena.scope()); + boolean result = (boolean) target.invokeExact(callback, testValue); + assertEquals(box[0], expected); + assertEquals(result, expected); + } + } + + 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 + { 0b1_0000_0000, false } // zero first byte + }; + } +} diff --git a/test/jdk/java/foreign/normalize/libNormalize.c b/test/jdk/java/foreign/normalize/libNormalize.c new file mode 100644 index 00000000000..4a21551278f --- /dev/null +++ b/test/jdk/java/foreign/normalize/libNormalize.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +// we use 'int' here to make sure the native code doesn't touch any of the bits +// the important part is that our Java code performs argument normalization +EXPORT int test(void (*cb)(int), int x) { + cb(x); // check upcall arg normalization + return x; // check return value normalization +} + +EXPORT int int_identity(int x) { + return x; +} diff --git a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java new file mode 100644 index 00000000000..9a745113e3f --- /dev/null +++ b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestPassHeapSegment + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; + +public class TestPassHeapSegment extends UpcallTestHelper { + + static { + System.loadLibrary("PassHeapSegment"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + 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 + } + + @Test(dataProvider = "specs") + public void testNoHeapReturns(boolean spec) throws IOException, InterruptedException { + runInNewProcess(Runner.class, spec).assertStdErrContains("Heap segment not allowed"); + } + + public static class Runner { + + static { + System.loadLibrary("PassHeapSegment"); + } + + public static void main(String[] args) throws Throwable { + MethodHandle handle = downcallHandle("test_return", FunctionDescriptor.ofVoid(ADDRESS)); + MemorySegment upcallStub = upcallStub(Runner.class, "target", FunctionDescriptor.of(ADDRESS)); + handle.invoke(upcallStub); + } + + public static MemorySegment target() { + return MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); // should throw + } + } + + @DataProvider + public static Object[][] specs() { + return new Object[][]{ + { true }, + { false } + }; + } +} + diff --git a/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c b/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c new file mode 100644 index 00000000000..fdb1981ac65 --- /dev/null +++ b/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void test_args(void* ptr) {} + +EXPORT void test_return(void* (*cb)(void)) { + cb(); +} diff --git a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java index 643bf3d9317..c9b3582d4d0 100644 --- a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java @@ -78,15 +78,14 @@ * TestAsyncStackWalk */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; -import java.lang.foreign.MemorySession; import jdk.test.whitebox.WhiteBox; import static java.lang.invoke.MethodHandles.lookup; @@ -116,17 +115,16 @@ public class TestAsyncStackWalk extends NativeTestHelper { static boolean didStackWalk; public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), session); - MemoryAddress stubAddress = stub.address(); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), arena.scope()); invocations = 0; didStackWalk = false; - payload(stubAddress); + payload(stub); assertTrue(didStackWalk); } } - static void payload(MemoryAddress cb) throws Throwable { + static void payload(MemorySegment cb) throws Throwable { MH_asyncStackWalk.invoke(cb); } diff --git a/test/jdk/java/foreign/stackwalk/TestStackWalk.java b/test/jdk/java/foreign/stackwalk/TestStackWalk.java index 23b56c5e219..9b3679c9f35 100644 --- a/test/jdk/java/foreign/stackwalk/TestStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestStackWalk.java @@ -78,11 +78,10 @@ * TestStackWalk */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -115,20 +114,19 @@ public class TestStackWalk extends NativeTestHelper { static boolean armed; public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), session); - MemoryAddress stubAddress = stub.address(); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), arena.scope()); armed = false; for (int i = 0; i < 20_000; i++) { - payload(stubAddress); // warmup + payload(stub); // warmup } armed = true; - payload(stubAddress); // test + payload(stub); // test } } - static void payload(MemoryAddress cb) throws Throwable { + static void payload(MemorySegment cb) throws Throwable { MH_foo.invoke(cb); Reference.reachabilityFence(cb); // keep oop alive across call } diff --git a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java index 4d82eb677fe..a0f36c479fc 100644 --- a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java +++ b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java @@ -40,10 +40,10 @@ * TestUpcallDeopt */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -79,8 +79,8 @@ public class TestUpcallDeopt extends NativeTestHelper { // we need to deoptimize through an uncommon trap in the callee of the optimized upcall stub // that is created when calling upcallStub below public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT), arena.scope()); armed = false; for (int i = 0; i < 20_000; i++) { payload(stub); // warmup @@ -91,8 +91,8 @@ public static void main(String[] args) throws Throwable { } } - static void payload(Addressable cb) throws Throwable { - MH_foo.invokeExact((Addressable) cb, 0, 1, 2, 3); + static void payload(MemorySegment cb) throws Throwable { + MH_foo.invokeExact(cb, 0, 1, 2, 3); Reference.reachabilityFence(cb); // keep oop alive across call } diff --git a/test/jdk/java/foreign/valist/VaListTest.java b/test/jdk/java/foreign/valist/VaListTest.java index e8846490e25..1972a89e657 100644 --- a/test/jdk/java/foreign/valist/VaListTest.java +++ b/test/jdk/java/foreign/valist/VaListTest.java @@ -40,6 +40,7 @@ */ import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; @@ -63,13 +64,9 @@ import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; 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 jdk.internal.foreign.PlatformLayouts.*; import static org.testng.Assert.*; @@ -80,11 +77,13 @@ public class VaListTest extends NativeTestHelper { System.loadLibrary("VaList"); } - private static final MethodHandle ADDRESS_TO_VALIST; + private static final MethodHandle VALIST_TO_ADDRESS; + private static final MethodHandle SEGMENT_TO_VALIST; static { try { - ADDRESS_TO_VALIST = MethodHandles.lookup().findStatic(VaList.class, "ofAddress", MethodType.methodType(VaList.class, MemoryAddress.class, MemorySession.class)); + VALIST_TO_ADDRESS = MethodHandles.lookup().findVirtual(VaList.class, "segment", MethodType.methodType(MemorySegment.class)); + SEGMENT_TO_VALIST = MethodHandles.lookup().findStatic(VaListTest.class, "segmentToValist", MethodType.methodType(VaList.class, MemorySegment.class)); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } @@ -113,7 +112,7 @@ private static MethodHandle link(String symbol, FunctionDescriptor fd) { } private static MethodHandle linkVaList(String symbol, FunctionDescriptor fd) { - return linkInternal(symbol, fd); + return MethodHandles.filterArguments(linkInternal(symbol, fd), fd.argumentLayouts().size() - 1, VALIST_TO_ADDRESS); } @@ -128,25 +127,25 @@ private static MethodHandle linkVaListCB(String symbol) { } private static final Function, VaList> winVaListFactory - = actions -> Windowsx64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> Windowsx64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> sysvVaListFactory - = actions -> SysVx64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> SysVx64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> linuxAArch64VaListFactory - = actions -> LinuxAArch64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> LinuxAArch64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> macAArch64VaListFactory - = actions -> MacOsAArch64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> MacOsAArch64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> platformVaListFactory - = (builder) -> VaList.make(builder, MemorySession.openConfined()); + = (builder) -> VaList.make(builder, SegmentScope.auto()); - private static final BiFunction, MemorySession, VaList> winVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> winVaListScopedFactory = Windowsx64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> sysvVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> sysvVaListScopedFactory = SysVx64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> linuxAArch64VaListScopedFactory + private static final BiFunction, SegmentScope, VaList> linuxAArch64VaListScopedFactory = LinuxAArch64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> macAArch64VaListScopedFactory + private static final BiFunction, SegmentScope, VaList> macAArch64VaListScopedFactory = MacOsAArch64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> platformVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> platformVaListScopedFactory = VaList::make; @DataProvider @@ -170,9 +169,9 @@ public void testIntSum(Function, VaList> vaListFactory, BiFunction sumInts, ValueLayout.OfInt intLayout) { VaList vaList = vaListFactory.apply(b -> - b.addVarg(intLayout, 10) - .addVarg(intLayout, 15) - .addVarg(intLayout, 20)); + b.addVarg(intLayout, 10) + .addVarg(intLayout, 15) + .addVarg(intLayout, 20)); int x = sumInts.apply(3, vaList); assertEquals(x, 45); } @@ -198,9 +197,9 @@ public void testDoubleSum(Function, VaList> vaListFacto BiFunction sumDoubles, ValueLayout.OfDouble doubleLayout) { VaList vaList = vaListFactory.apply(b -> - b.addVarg(doubleLayout, 3.0D) - .addVarg(doubleLayout, 4.0D) - .addVarg(doubleLayout, 5.0D)); + b.addVarg(doubleLayout, 3.0D) + .addVarg(doubleLayout, 4.0D) + .addVarg(doubleLayout, 5.0D)); double x = sumDoubles.apply(3, vaList); assertEquals(x, 12.0D); } @@ -210,7 +209,7 @@ public void testDoubleSum(Function, VaList> vaListFacto public static Object[][] pointers() { Function> getIntJavaFact = layout -> list -> { - MemoryAddress ma = list.nextVarg(layout); + MemorySegment ma = list.nextVarg(layout); return ma.get(JAVA_INT, 0); }; Function getIntNative = MethodHandleProxies.asInterfaceInstance(Function.class, MH_getInt); @@ -224,13 +223,13 @@ public static Object[][] pointers() { } @Test(dataProvider = "pointers") - public void testVaListMemoryAddress(Function, VaList> vaListFactory, + public void testVaListMemorySegment(Function, VaList> vaListFactory, Function getFromPointer, ValueLayout.OfAddress pointerLayout) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment msInt = MemorySegment.allocateNative(JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment msInt = MemorySegment.allocateNative(JAVA_INT, arena.scope());; msInt.set(JAVA_INT, 0, 10); - VaList vaList = vaListFactory.apply(b -> b.addVarg(pointerLayout, msInt.address())); + VaList vaList = vaListFactory.apply(b -> b.addVarg(pointerLayout, msInt)); int x = getFromPointer.apply(vaList); assertEquals(x, 10); } @@ -246,7 +245,7 @@ public static Object[][] structs() { TriFunction> sumStructJavaFact = (pointLayout, VH_Point_x, VH_Point_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(pointLayout, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(pointLayout, SegmentScope.auto()); list.nextVarg(pointLayout, SegmentAllocator.prefixAllocator(struct)); int x = (int) VH_Point_x.get(struct); int y = (int) VH_Point_y.get(struct); @@ -282,8 +281,8 @@ public static Object[][] structs() { public void testStruct(Function, VaList> vaListFactory, Function sumStruct, GroupLayout Point_LAYOUT, VarHandle VH_Point_x, VarHandle VH_Point_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, arena.scope());; VH_Point_x.set(struct, 5); VH_Point_y.set(struct, 10); @@ -299,7 +298,7 @@ public static Object[][] bigStructs() { TriFunction> sumStructJavaFact = (BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); list.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_BigPoint_x.get(struct); long y = (long) VH_BigPoint_y.get(struct); @@ -335,8 +334,8 @@ public static Object[][] bigStructs() { public void testBigStruct(Function, VaList> vaListFactory, Function sumBigStruct, GroupLayout BigPoint_LAYOUT, VarHandle VH_BigPoint_x, VarHandle VH_BigPoint_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, arena.scope());; VH_BigPoint_x.set(struct, 5); VH_BigPoint_y.set(struct, 10); @@ -352,7 +351,7 @@ public static Object[][] floatStructs() { TriFunction> sumStructJavaFact = (FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, SegmentScope.auto()); list.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); float x = (float) VH_FloatPoint_x.get(struct); float y = (float) VH_FloatPoint_y.get(struct); @@ -389,8 +388,8 @@ public void testFloatStruct(Function, VaList> vaListFac Function sumFloatStruct, GroupLayout FloatPoint_LAYOUT, VarHandle VH_FloatPoint_x, VarHandle VH_FloatPoint_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, arena.scope());; VH_FloatPoint_x.set(struct, 1.234f); VH_FloatPoint_y.set(struct, 3.142f); @@ -410,7 +409,7 @@ public static Object[][] hugeStructs() { QuadFunc> sumStructJavaFact = (HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, SegmentScope.auto()); list.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_HugePoint_x.get(struct); long y = (long) VH_HugePoint_y.get(struct); @@ -453,8 +452,8 @@ public void testHugeStruct(Function, VaList> vaListFact VarHandle VH_HugePoint_x, VarHandle VH_HugePoint_y, VarHandle VH_HugePoint_z) { // On AArch64 a struct needs to be larger than 16 bytes to be // passed by reference. - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, arena.scope());; VH_HugePoint_x.set(struct, 1); VH_HugePoint_y.set(struct, 2); VH_HugePoint_z.set(struct, 3); @@ -486,7 +485,7 @@ public static Object[][] sumStack() { }; SumStackFunc sumStackNative = (longSum, doubleSum, list) -> { try { - MH_sumStack.invoke(longSum, doubleSum, list); + MH_sumStack.invokeExact(longSum, doubleSum, list); } catch (Throwable ex) { throw new AssertionError(ex); } @@ -505,9 +504,9 @@ public void testStack(Function, VaList> vaListFactory, SumStackFunc sumStack, ValueLayout.OfLong longLayout, ValueLayout.OfDouble doubleLayout) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment longSum = MemorySegment.allocateNative(longLayout, session); - MemorySegment doubleSum = MemorySegment.allocateNative(doubleLayout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment longSum = MemorySegment.allocateNative(longLayout, arena.scope());; + MemorySegment doubleSum = MemorySegment.allocateNative(doubleLayout, arena.scope());; longSum.set(JAVA_LONG, 0, 0L); doubleSum.set(JAVA_DOUBLE, 0, 0D); @@ -533,9 +532,9 @@ public void testStack(Function, VaList> vaListFactory, @Test(dataProvider = "upcalls") public void testUpcall(MethodHandle target, MethodHandle callback) throws Throwable { FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_POINTER); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = abi.upcallStub(callback, desc, session); - target.invoke(stub); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = abi.upcallStub(callback, desc, arena.scope()); + target.invokeExact(stub); } } @@ -570,18 +569,18 @@ public static Object[][] sumIntsScoped() { } @Test(dataProvider = "sumIntsScoped") - public void testScopedVaList(BiFunction, MemorySession, VaList> vaListFactory, + public void testScopedVaList(BiFunction, SegmentScope, VaList> vaListFactory, BiFunction sumInts, ValueLayout.OfInt intLayout) { VaList listLeaked; - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); int x = sumInts.apply(2, list); assertEquals(x, 12); listLeaked = list; } - assertFalse(listLeaked.session().isAlive()); + assertFalse(listLeaked.segment().scope().isAlive()); } @Test(dataProvider = "structs") @@ -589,21 +588,21 @@ public void testScopeMSRead(Function, VaList> vaListFac Function sumStruct, // ignored GroupLayout Point_LAYOUT, VarHandle VH_Point_x, VarHandle VH_Point_y) { MemorySegment pointOut; - try (MemorySession session = MemorySession.openConfined()) { - try (MemorySession innerSession = MemorySession.openConfined()) { - MemorySegment pointIn = MemorySegment.allocateNative(Point_LAYOUT, innerSession); + try (Arena arena = Arena.openConfined()) { + try (Arena innerArena = Arena.openConfined()) { + MemorySegment pointIn = MemorySegment.allocateNative(Point_LAYOUT, innerArena.scope());; VH_Point_x.set(pointIn, 3); VH_Point_y.set(pointIn, 6); VaList list = vaListFactory.apply(b -> b.addVarg(Point_LAYOUT, pointIn)); - pointOut = MemorySegment.allocateNative(Point_LAYOUT, session); + pointOut = MemorySegment.allocateNative(Point_LAYOUT, arena.scope());; list.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(pointOut)); assertEquals((int) VH_Point_x.get(pointOut), 3); assertEquals((int) VH_Point_y.get(pointOut), 6); - assertTrue(pointOut.session().isAlive()); // after VaList freed + assertTrue(pointOut.scope().isAlive()); // after VaList freed } - assertTrue(pointOut.session().isAlive()); // after inner session freed + assertTrue(pointOut.scope().isAlive()); // after inner session freed } - assertFalse(pointOut.session().isAlive()); // after outer session freed + assertFalse(pointOut.scope().isAlive()); // after outer session freed } @DataProvider @@ -617,10 +616,10 @@ public Object[][] copy() { } @Test(dataProvider = "copy") - public void testCopy(BiFunction, MemorySession, VaList> vaListFactory, ValueLayout.OfInt intLayout) { - try (var session = MemorySession.openConfined()) { + public void testCopy(BiFunction, SegmentScope, VaList> vaListFactory, ValueLayout.OfInt intLayout) { + try (var arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); VaList copy = list.copy(); assertEquals(copy.nextVarg(intLayout), 4); assertEquals(copy.nextVarg(intLayout), 8); @@ -639,12 +638,12 @@ public void testCopy(BiFunction, MemorySession, VaList> @Test(dataProvider = "copy", expectedExceptions = IllegalStateException.class) - public void testCopyUnusableAfterOriginalClosed(BiFunction, MemorySession, VaList> vaListFactory, + public void testCopyUnusableAfterOriginalClosed(BiFunction, SegmentScope, VaList> vaListFactory, ValueLayout.OfInt intLayout) { VaList copy; - try (var session = MemorySession.openConfined()) { + try (var arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); copy = list.copy(); } @@ -682,14 +681,14 @@ public static Object[][] upcalls() { return new Object[][]{ { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { VaList copy = vaList.copy(); - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); @@ -703,7 +702,7 @@ public static Object[][] upcalls() { assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); @@ -715,28 +714,27 @@ public static Object[][] upcalls() { assertEquals(vaList.nextVarg(C_LONG_LONG), 42); })}, { linkVaListCB("upcallStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, SegmentScope.auto()); vaList.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((int) VH_Point_x.get(struct), 5); assertEquals((int) VH_Point_y.get(struct), 10); })}, { linkVaListCB("upcallHugeStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_HugePoint_x.get(struct), 1); assertEquals((long) VH_HugePoint_y.get(struct), 2); assertEquals((long) VH_HugePoint_z.get(struct), 3); })}, { linkVaListCB("upcallFloatStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((float) VH_FloatPoint_x.get(struct), 1.0f); assertEquals((float) VH_FloatPoint_y.get(struct), 2.0f); })}, { linkVaListCB("upcallMemoryAddress"), VaListConsumer.mh(vaList -> { - MemoryAddress intPtr = vaList.nextVarg(C_POINTER); - MemorySegment ms = MemorySegment.ofAddress(intPtr, C_INT.byteSize(), MemorySession.global()); - int x = ms.get(JAVA_INT, 0); + MemorySegment intPtr = vaList.nextVarg(C_POINTER); + int x = intPtr.get(JAVA_INT, 0); assertEquals(x, 10); })}, { linkVaListCB("upcallDoubles"), VaListConsumer.mh(vaList -> { @@ -774,7 +772,7 @@ public static Object[][] upcalls() { assertEquals((float) vaList.nextVarg(C_DOUBLE), 13.0F); assertEquals(vaList.nextVarg(C_DOUBLE), 14.0D); - MemorySegment buffer = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment buffer = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); SegmentAllocator bufferAllocator = SegmentAllocator.prefixAllocator(buffer); MemorySegment point = vaList.nextVarg(Point_LAYOUT, bufferAllocator); @@ -816,13 +814,17 @@ static MethodHandle mh(VaListConsumer instance) { MethodHandle handle = MethodHandles.lookup().findVirtual(VaListConsumer.class, "accept", MethodType.methodType(void.class, VaList.class)).bindTo(instance); return MethodHandles.filterArguments(handle, 0, - MethodHandles.insertArguments(ADDRESS_TO_VALIST, 1, MemorySession.openConfined())); + SEGMENT_TO_VALIST); } catch (ReflectiveOperationException e) { throw new InternalError(e); } } } + static VaList segmentToValist(MemorySegment segment) { + return VaList.ofAddress(segment.address(), SegmentScope.auto()); + } + @DataProvider public static Object[][] overflow() { List, VaList>> factories = List.of( @@ -868,7 +870,7 @@ private static void buildVaList(VaList.Builder builder, List conte } else if (layout instanceof ValueLayout.OfDouble ofDouble) { builder.addVarg(ofDouble, 1D); } else if (layout instanceof ValueLayout.OfAddress ofAddress) { - builder.addVarg(ofAddress, MemoryAddress.ofLong(1)); + builder.addVarg(ofAddress, MemorySegment.ofAddress(1)); } } } @@ -890,7 +892,7 @@ private static void nextVarg(VaList vaList, MemoryLayout layout) { } else if (layout instanceof ValueLayout.OfDouble ofDouble) { assertEquals(vaList.nextVarg(ofDouble), 1D); } else if (layout instanceof ValueLayout.OfAddress ofAddress) { - assertEquals(vaList.nextVarg(ofAddress), MemoryAddress.ofLong(1)); + assertEquals(vaList.nextVarg(ofAddress), MemorySegment.ofAddress(1)); } } @@ -905,4 +907,8 @@ public void testVargOverflow(Function, VaList> vaListFa assertThrows(NoSuchElementException.class, () -> nextVarg(vaList, next)); } + @Test(dataProvider = "emptyVaLists") + public void testEmptyVaListScope(VaList vaList) { + assertEquals(vaList.segment().scope(), SegmentScope.global()); + } } diff --git a/test/jdk/java/foreign/virtual/TestVirtualCalls.java b/test/jdk/java/foreign/virtual/TestVirtualCalls.java index 7f0e7f1f1ff..eacccd4d893 100644 --- a/test/jdk/java/foreign/virtual/TestVirtualCalls.java +++ b/test/jdk/java/foreign/virtual/TestVirtualCalls.java @@ -31,10 +31,10 @@ * TestVirtualCalls */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import org.testng.annotations.*; @@ -46,9 +46,9 @@ public class TestVirtualCalls extends NativeTestHelper { static final Linker abi = Linker.nativeLinker(); static final MethodHandle func; - static final Addressable funcA; - static final Addressable funcB; - static final Addressable funcC; + static final MemorySegment funcA; + static final MemorySegment funcB; + static final MemorySegment funcC; static { func = abi.downcallHandle( @@ -69,7 +69,7 @@ public void testVirtualCalls() throws Throwable { @Test(expectedExceptions = NullPointerException.class) public void testNullTarget() throws Throwable { - int x = (int) func.invokeExact((Addressable) null); + int x = (int) func.invokeExact((MemorySegment)null); } } diff --git a/test/jdk/java/io/Console/ModuleSelectionTest.java b/test/jdk/java/io/Console/ModuleSelectionTest.java new file mode 100644 index 00000000000..3ecf9a1a6fa --- /dev/null +++ b/test/jdk/java/io/Console/ModuleSelectionTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8295803 8299689 + * @summary Tests System.console() returns correct Console (or null) from the expected + * module. + * @modules java.base/java.io:+open + * @run main/othervm ModuleSelectionTest java.base + * @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le + * @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base + * @run main/othervm --limit-modules java.base ModuleSelectionTest java.base + */ + +import java.io.Console; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class ModuleSelectionTest { + public static void main(String... args) throws Throwable { + var con = System.console(); + var pc = Class.forName("java.io.ProxyingConsole"); + var jdkc = Class.forName("jdk.internal.io.JdkConsole"); + var istty = (boolean)MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup()) + .findStatic(Console.class, "istty", MethodType.methodType(boolean.class)) + .invoke(); + var impl = con != null ? MethodHandles.privateLookupIn(pc, MethodHandles.lookup()) + .findGetter(pc, "delegate", jdkc) + .invoke(con) : null; + + var expected = switch (args[0]) { + case "java.base" -> istty ? "java.base" : "null"; + default -> args[0]; + }; + var actual = con == null ? "null" : impl.getClass().getModule().getName(); + + if (!actual.equals(expected)) { + throw new RuntimeException(""" + Console implementation is not the expected one. + Expected: %s + Actual: %s + """.formatted(expected, actual)); + } else { + System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty); + } + } +} diff --git a/test/jdk/java/io/Console/RedirectTest.java b/test/jdk/java/io/Console/RedirectTest.java new file mode 100644 index 00000000000..d7aa6c64468 --- /dev/null +++ b/test/jdk/java/io/Console/RedirectTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.File; +import java.nio.file.Files; + +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @bug 8295803 8299689 + * @summary Tests System.console() works with standard input redirection. + * @library /test/lib + * @run main RedirectTest + * @run main/othervm -Djdk.console=jdk.internal.le RedirectTest + */ +public class RedirectTest { + private static final String SYSPROP = "jdk.console"; + + public static void main(String... args) throws Throwable { + if (args.length == 0) { + // no arg will launch the child process that actually perform tests + var pb = ProcessTools.createTestJvm( + "-D" + SYSPROP + "=" + System.getProperty(SYSPROP, ""), + "RedirectTest", "dummy"); + var input = new File(System.getProperty("test.src", "."), "input.txt"); + pb.redirectInput(input); + var oa = ProcessTools.executeProcess(pb); + if (oa.getExitValue() == 1) { + System.out.println("System.console() returns null. Ignoring the test."); + } else { + var output = oa.asLines(); + var expected = Files.readAllLines(input.toPath()); + if (!output.equals(expected)) { + throw new RuntimeException(""" + Standard out had unexpected strings: + Actual output: %s + Expected output: %s + """.formatted(output, expected)); + } else { + oa.shouldHaveExitValue(0); + System.out.println("Redirect succeeded."); + } + } + } else { + var con = System.console(); + if (con != null) { + String line; + while ((line = con.readLine()) != null) { + System.out.println(line); + } + } else { + // Exit with 1 + System.exit(1); + } + } + } +} diff --git a/test/jdk/java/io/Console/SecurityManagerTest.java b/test/jdk/java/io/Console/SecurityManagerTest.java new file mode 100644 index 00000000000..5eed29a7669 --- /dev/null +++ b/test/jdk/java/io/Console/SecurityManagerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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 8295803 + * @summary Tests System.console() works with the security manager + * @run main/othervm/java.security.policy=test.policy -Djava.security.manager -Djdk.console=jdk.internal.le SecurityManagerTest + */ +public class SecurityManagerTest { + public static void main(String... args) { + System.console(); + // consider it successful if ServiceConfigurationError was not thrown here + } +} diff --git a/test/jdk/java/io/Console/input.txt b/test/jdk/java/io/Console/input.txt new file mode 100644 index 00000000000..9387db2c697 --- /dev/null +++ b/test/jdk/java/io/Console/input.txt @@ -0,0 +1,3 @@ +This is line 1 +This is line 2 +This is the last line diff --git a/test/jdk/java/io/Console/test.policy b/test/jdk/java/io/Console/test.policy new file mode 100644 index 00000000000..61fda0ca63a --- /dev/null +++ b/test/jdk/java/io/Console/test.policy @@ -0,0 +1,3 @@ +grant { + permission java.io.FilePermission "<>","read,write,delete"; +}; diff --git a/test/jdk/java/io/File/Basic.java b/test/jdk/java/io/File/Basic.java index e54606c6b6d..603249c08f8 100644 --- a/test/jdk/java/io/File/Basic.java +++ b/test/jdk/java/io/File/Basic.java @@ -29,10 +29,8 @@ */ import java.io.FileOutputStream; -import java.io.IOException; import java.io.File; import java.io.PrintStream; -import java.io.RandomAccessFile; public class Basic { diff --git a/test/jdk/java/io/SequenceInputStream/TransferTo.java b/test/jdk/java/io/SequenceInputStream/TransferTo.java new file mode 100644 index 00000000000..a39d2c1e013 --- /dev/null +++ b/test/jdk/java/io/SequenceInputStream/TransferTo.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.SequenceInputStream; +import java.util.Arrays; +import java.util.Random; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.testng.annotations.Test; + +import jdk.test.lib.RandomFactory; + +import static java.lang.String.format; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run testng/othervm/timeout=180 TransferTo + * @bug 8297298 + * @summary Tests whether java.io.SequenceInputStream.transferTo conforms to the + * InputStream.transferTo specification + * @key randomness + */ +public class TransferTo { + private static final int MIN_SIZE = 10_000; + private static final int MAX_SIZE_INCR = 100_000_000 - MIN_SIZE; + + private static final int ITERATIONS = 10; + + private static final Random RND = RandomFactory.getRandom(); + + /* + * Testing API compliance: input stream must throw NullPointerException + * when parameter "out" is null. + */ + @Test + public void testNullPointerException() throws Exception { + // factory for incoming data provider + InputStreamProvider inputStreamProvider = byteArrayInput(); + + // tests empty input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input().transferTo(null)); + + // tests single-byte input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input((byte) 1).transferTo(null)); + + // tests dual-byte input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input((byte) 1, (byte) 2).transferTo(null)); + } + + /* + * Testing API compliance: complete content of input stream must be + * transferred to output stream. + */ + @Test + public void testStreamContents() throws Exception { + // factory for incoming data provider + InputStreamProvider inputStreamProvider = byteArrayInput(); + + // factory for outgoing data recorder + OutputStreamProvider outputStreamProvider = byteArrayOutput(); + + // tests empty input stream + checkTransferredContents(inputStreamProvider, + outputStreamProvider, new byte[0]); + + // tests input stream with a length between 1k and 4k + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(1024, 4096)); + + // tests input stream with several data chunks, as 16k is more than a + // single chunk can hold + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(16384, 16384)); + + // tests randomly chosen starting positions within source and + // target stream + for (int i = 0; i < ITERATIONS; i++) { + byte[] inBytes = createRandomBytes(MIN_SIZE, MAX_SIZE_INCR); + int posIn = RND.nextInt(inBytes.length); + int posOut = RND.nextInt(MIN_SIZE); + checkTransferredContents(inputStreamProvider, + outputStreamProvider, inBytes, posIn, posOut); + } + + // tests reading beyond source EOF (must not transfer any bytes) + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(4096, 0), 4096, 0); + + // tests writing beyond target EOF (must extend output stream) + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(4096, 0), 0, 4096); + } + + /* + * Asserts that the transferred content is correct, i.e., compares the bytes + * actually transferred to those expected. The position of the input and + * output streams before the transfer are zero (BOF). + */ + private static void checkTransferredContents(InputStreamProvider inputStreamProvider, + OutputStreamProvider outputStreamProvider, byte[] inBytes) throws Exception { + checkTransferredContents(inputStreamProvider, + outputStreamProvider, inBytes, 0, 0); + } + + /* + * Asserts that the transferred content is correct, i. e. compares the bytes + * actually transferred to those expected. The positions of the input and + * output streams before the transfer are provided by the caller. + */ + private static void checkTransferredContents(InputStreamProvider inputStreamProvider, + OutputStreamProvider outputStreamProvider, byte[] inBytes, int posIn, + int posOut) throws Exception { + AtomicReference> recorder = new AtomicReference<>(); + try (InputStream in = inputStreamProvider.input(inBytes); + OutputStream out = outputStreamProvider.output(recorder::set)) { + // skip bytes until starting position + in.skipNBytes(posIn); + out.write(new byte[posOut]); + + long reported = in.transferTo(out); + int count = inBytes.length - posIn; + + assertEquals(reported, count, + format("reported %d bytes but should report %d", reported, count)); + + byte[] outBytes = recorder.get().get(); + assertTrue(Arrays.equals(inBytes, posIn, posIn + count, + outBytes, posOut, posOut + count), + format("inBytes.length=%d, outBytes.length=%d", count, outBytes.length)); + } + } + + /* + * Creates an array of random size (between min and min + maxRandomAdditive) + * filled with random bytes + */ + private static byte[] createRandomBytes(int min, int maxRandomAdditive) { + byte[] bytes = new byte[min + + (maxRandomAdditive == 0 ? 0 : RND.nextInt(maxRandomAdditive))]; + RND.nextBytes(bytes); + return bytes; + } + + private interface InputStreamProvider { + InputStream input(byte... bytes) throws Exception; + } + + private interface OutputStreamProvider { + OutputStream output(Consumer> spy) throws Exception; + } + + private static InputStreamProvider byteArrayInput() { + return bytes -> { + InputStream is1 = new ByteArrayInputStream(bytes, 0, bytes.length / 2); + InputStream is2 = new ByteArrayInputStream(bytes, bytes.length / 2, bytes.length); + return new SequenceInputStream(is1, is2); + }; + } + + private static OutputStreamProvider byteArrayOutput() { + return new OutputStreamProvider() { + @Override + public OutputStream output(Consumer> spy) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + spy.accept(outputStream::toByteArray); + return outputStream; + } + }; + } + +} diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index 3056eba8b83..acb162ad947 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4533872 4985214 4985217 4993841 5017268 5017280 + * @bug 4533872 4985214 4985217 4993841 5017268 5017280 8298033 * @summary Unit tests for supplementary character support (JSR-204) * @compile Supplementary.java * @run main/timeout=600 Supplementary @@ -797,12 +797,12 @@ private static void callCodePoint(boolean isAt, char[] a, int index, } private static void callCodePoint(boolean isAt, char[] a, int index, int limit, - Class expectedException) { + Class expectedException) { try { int c = isAt ? Character.codePointAt(a, index, limit) : Character.codePointBefore(a, index, limit); } catch (Exception e) { - if (expectedException.isInstance(e)) { + if (expectedException == e.getClass()) { return; } throw new RuntimeException("Unspecified exception", e); diff --git a/test/jdk/java/lang/String/StringRepeat.java b/test/jdk/java/lang/String/StringRepeat.java index 491bfe9f86f..c36e512f8ba 100644 --- a/test/jdk/java/lang/String/StringRepeat.java +++ b/test/jdk/java/lang/String/StringRepeat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -31,6 +31,7 @@ * @test * @summary This exercises String#repeat patterns with 16 * 1024 * 1024 repeats. * @requires os.maxMemory >= 2G + * @requires !(os.family == "windows" & sun.arch.data.model == "32") * @run main/othervm -Xmx2g StringRepeat 16777216 */ diff --git a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java index ae5d5a6f2bf..5e676da446b 100644 --- a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java +++ b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java @@ -58,11 +58,11 @@ public static void main(String[] args) throws Throwable { .findStatic(ImplicitAttach.class, "callback", MethodType.methodType(void.class)); MemorySegment upcallStub = abi.upcallStub(callback, FunctionDescriptor.ofVoid(), - MemorySession.global()); + SegmentScope.global()); // void start_threads(int count, void *(*f)(void *)) SymbolLookup symbolLookup = SymbolLookup.loaderLookup(); - MemorySegment symbol = symbolLookup.lookup("start_threads").orElseThrow(); + MemorySegment symbol = symbolLookup.find("start_threads").orElseThrow(); FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_INT, C_POINTER); MethodHandle start_threads = abi.downcallHandle(symbol, desc); diff --git a/test/jdk/java/lang/Thread/virtual/HoldsLock.java b/test/jdk/java/lang/Thread/virtual/HoldsLock.java index 727362a11a5..016cc736d2e 100644 --- a/test/jdk/java/lang/Thread/virtual/HoldsLock.java +++ b/test/jdk/java/lang/Thread/virtual/HoldsLock.java @@ -35,6 +35,7 @@ * @summary Test Thread.holdsLock when lock held by carrier thread * @requires vm.continuations & vm.debug * @modules java.base/java.lang:+open + * @enablePreview * @run testng/othervm -XX:+UseHeavyMonitors HoldsLock */ diff --git a/test/jdk/java/lang/Thread/virtual/YieldQueuing.java b/test/jdk/java/lang/Thread/virtual/YieldQueuing.java new file mode 100644 index 00000000000..33961848667 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/YieldQueuing.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 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 + * @summary Test Thread.yield submits the virtual thread task to the expected queue + * @requires vm.continuations + * @enablePreview + * @run junit/othervm -Djdk.virtualThreadScheduler.maxPoolSize=1 YieldQueuing + */ + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class YieldQueuing { + + /** + * Test Thread.yield submits the task for the current virtual thread to a scheduler + * submission queue when there are no tasks in the local queue. + */ + @Test + void testYieldWithEmptyLocalQueue() throws Exception { + var list = new CopyOnWriteArrayList(); + + var threadsStarted = new AtomicBoolean(); + + var threadA = Thread.ofVirtual().unstarted(() -> { + // pin thread until task for B is in submission queue + while (!threadsStarted.get()) { + Thread.onSpinWait(); + } + + list.add("A"); + Thread.yield(); // push task for A to submission queue, B should run + list.add("A"); + }); + + var threadB = Thread.ofVirtual().unstarted(() -> { + list.add("B"); + }); + + // push tasks for A and B to submission queue + threadA.start(); + threadB.start(); + + // release A + threadsStarted.set(true); + + // wait for result + threadA.join(); + threadB.join(); + assertEquals(list, List.of("A", "B", "A")); + } + + /** + * Test Thread.yield submits the task for the current virtual thread to the local + * queue when there are tasks in the local queue. + */ + @Test + void testYieldWithNonEmptyLocalQueue() throws Exception { + var list = new CopyOnWriteArrayList(); + + var threadsStarted = new AtomicBoolean(); + + var threadA = Thread.ofVirtual().unstarted(() -> { + // pin thread until tasks for B and C are in submission queue + while (!threadsStarted.get()) { + Thread.onSpinWait(); + } + + list.add("A"); + LockSupport.park(); // B should run + list.add("A"); + }); + + var threadB = Thread.ofVirtual().unstarted(() -> { + list.add("B"); + LockSupport.unpark(threadA); // push task for A to local queue + Thread.yield(); // push task for B to local queue, A should run + list.add("B"); + }); + + var threadC = Thread.ofVirtual().unstarted(() -> { + list.add("C"); + }); + + // push tasks for A, B and C to submission queue + threadA.start(); + threadB.start(); + threadC.start(); + + // release A + threadsStarted.set(true); + + // wait for result + threadA.join(); + threadB.join(); + threadC.join(); + assertEquals(list, List.of("A", "B", "A", "B", "C")); + } +} diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java index 34b19e0e0f3..a81726983ba 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java @@ -35,6 +35,7 @@ * @test * @requires vm.debug == true & vm.continuations * @modules java.base/java.lang:+open + * @enablePreview * @compile GetStackTraceALot.java ../ThreadBuilders.java * @run main/timeout=300 GetStackTraceALot 1000 */ diff --git a/test/jdk/java/lang/Thread/virtual/stress/Skynet.java b/test/jdk/java/lang/Thread/virtual/stress/Skynet.java index 82bba078509..ed21adfecab 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/Skynet.java +++ b/test/jdk/java/lang/Thread/virtual/stress/Skynet.java @@ -26,7 +26,7 @@ * @summary Stress test virtual threads with a variation of the Skynet 1M benchmark * @requires vm.continuations * @enablePreview - * @run main/othervm/timeout=300 Skynet + * @run main/othervm/timeout=300 -Xmx1g Skynet */ /* @@ -35,7 +35,7 @@ * @requires vm.gc.Z * @enablePreview * @run main/othervm/timeout=300 -XX:+UnlockDiagnosticVMOptions - * -XX:+ZVerifyViews -XX:ZCollectionInterval=0.01 Skynet + * -XX:+ZVerifyViews -XX:ZCollectionInterval=0.01 -Xmx1g Skynet */ import java.util.concurrent.BlockingQueue; diff --git a/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java b/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java index 327ca0e4fd4..51381f12b02 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java @@ -26,7 +26,7 @@ * @summary Stress test Thread.yield * @requires vm.debug != true * @enablePreview - * @run main YieldALot 500000 + * @run main YieldALot 350000 */ /* diff --git a/test/jdk/java/lang/ThreadGroup/BasicTests.java b/test/jdk/java/lang/ThreadGroup/BasicTests.java index 857983eacbb..4829a547848 100644 --- a/test/jdk/java/lang/ThreadGroup/BasicTests.java +++ b/test/jdk/java/lang/ThreadGroup/BasicTests.java @@ -750,13 +750,6 @@ public void testStop() { assertThrows(UnsupportedOperationException.class, () -> group.stop()); } - @Test - public void testAllowThreadSuspension() { - ThreadGroup group = new ThreadGroup("foo"); - assertFalse(group.allowThreadSuspension(false)); - assertFalse(group.allowThreadSuspension(true)); - } - @Test public void testNull1() { assertThrows(NullPointerException.class, diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 403c8d2d2b4..c80e3304613 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -288,7 +288,7 @@ * -Xbatch -XX:TieredStopAtLevel=1 * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large * - * @run main/othervm -Xmx8g + * @run main/othervm/timeout=180 -Xmx8g * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -Xbatch -XX:-TieredCompilation * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java index fa29d2a85e2..8241b440031 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java @@ -46,9 +46,9 @@ * VarHandleTestExact */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import org.testng.SkipException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -101,7 +101,7 @@ public void testExactSet(String fieldBaseName, Class fieldType, boolean ro, O doTest(vh, tvh -> tvh.set(w, testValue), tvh -> setter.set(tvh, w, testValue), - ".*\\Qexpected (Widget," + fieldType.getSimpleName() + ")void \\E.*"); + ".*\\Qhandle's method type (Widget," + fieldType.getSimpleName() + ")void \\E.*"); } @Test(dataProvider = "dataObjectAccess") @@ -115,7 +115,7 @@ public void testExactGet(String fieldBaseName, Class fieldType, boolean ro, O doTest(vh, tvh -> tvh.get(w), tvh -> getter.get(tvh, w), - ".*\\Qexpected (Widget)" + fieldType.getSimpleName() + " \\E.*"); + ".*\\Qhandle's method type (Widget)" + fieldType.getSimpleName() + " \\E.*"); } @Test(dataProvider = "dataObjectAccess") @@ -129,7 +129,7 @@ public void testExactSetStatic(String fieldBaseName, Class fieldType, boolean doTest(vh, tvh -> tvh.set(testValue), tvh -> staticSetter.set(tvh, testValue), - ".*\\Qexpected (" + fieldType.getSimpleName() + ")void \\E.*"); + ".*\\Qhandle's method type (" + fieldType.getSimpleName() + ")void \\E.*"); } @Test(dataProvider = "dataObjectAccess") @@ -142,7 +142,7 @@ public void testExactGetStatic(String fieldBaseName, Class fieldType, boolean doTest(vh, tvh -> tvh.get(), tvh -> staticGetter.get(tvh), - ".*\\Qexpected ()" + fieldType.getSimpleName() + " \\E.*"); + ".*\\Qhandle's method type ()" + fieldType.getSimpleName() + " \\E.*"); } @Test(dataProvider = "dataSetArray") @@ -153,7 +153,7 @@ public void testExactArraySet(Class arrayClass, Object testValue, SetArrayX s doTest(vh, tvh -> tvh.set(arr, 0, testValue), tvh -> setter.set(tvh, arr, testValue), - ".*\\Qexpected (" + arrayClass.getSimpleName() + ",int," + arrayClass.componentType().getSimpleName() + ")void \\E.*"); + ".*\\Qhandle's method type (" + arrayClass.getSimpleName() + ",int," + arrayClass.componentType().getSimpleName() + ")void \\E.*"); } @Test(dataProvider = "dataSetBuffer") @@ -164,18 +164,18 @@ public void testExactBufferSet(Class arrayClass, Object testValue, SetBufferX doTest(vh, tvh -> tvh.set(buff, 0, testValue), tvh -> setter.set(tvh, buff, testValue), - ".*\\Qexpected (ByteBuffer,int," + arrayClass.componentType().getSimpleName() + ")void \\E.*"); + ".*\\Qhandle's method type (ByteBuffer,int," + arrayClass.componentType().getSimpleName() + ")void \\E.*"); } @Test(dataProvider = "dataSetMemorySegment") public void testExactSegmentSet(Class carrier, Object testValue, SetSegmentX setter) { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(MemoryLayout.valueLayout(carrier, ByteOrder.nativeOrder())); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(8, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = arena.allocate(8); doTest(vh, tvh -> tvh.set(seg, 0L, testValue), tvh -> setter.set(tvh, seg, 0L, testValue), - ".*\\Qexpected (MemorySegment,long," + carrier.getSimpleName() + ")void \\E.*"); + ".*\\Qhandle's method type (MemorySegment,long," + carrier.getSimpleName() + ")void \\E.*"); } } diff --git a/test/jdk/java/lang/invoke/WrongMethodTypeTest.java b/test/jdk/java/lang/invoke/WrongMethodTypeTest.java new file mode 100644 index 00000000000..be0c59e0d77 --- /dev/null +++ b/test/jdk/java/lang/invoke/WrongMethodTypeTest.java @@ -0,0 +1,85 @@ +/* + * 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 8299183 + * @run testng WrongMethodTypeTest + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.VarHandle; +import java.lang.invoke.WrongMethodTypeException; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +public class WrongMethodTypeTest { + static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public void checkExactType() throws Throwable { + String expectedMessage = "handle's method type (int)int but found ()boolean"; + try { + MethodHandle mh = LOOKUP.findStatic(WrongMethodTypeTest.class, "m", methodType(int.class, int.class)); + boolean b = (boolean)mh.invokeExact(); + fail("Expected WrongMethodTypeException"); + } catch (WrongMethodTypeException ex) { + assertEquals(expectedMessage, ex.getMessage()); + } + } + + @Test + public void checkAccessModeInvokeExact() throws Throwable { + String expectedMessage = "handle's method type ()int but found ()Void"; + VarHandle vh = LOOKUP.findStaticVarHandle(WrongMethodTypeTest.class, "x", int.class) + .withInvokeExactBehavior(); + try { + Void o = (Void) vh.get(); + } catch (WrongMethodTypeException ex) { + assertEquals(expectedMessage, ex.getMessage()); + } + } + + @Test + public void checkVarHandleInvokeExact() throws Throwable { + String expectedMessage = "handle's method type (WrongMethodTypeTest)boolean but found (WrongMethodTypeTest)int"; + VarHandle vh = LOOKUP.findVarHandle(WrongMethodTypeTest.class, "y", boolean.class) + .withInvokeExactBehavior(); + try { + int o = (int) vh.get(new WrongMethodTypeTest()); + } catch (WrongMethodTypeException ex) { + assertEquals(expectedMessage, ex.getMessage()); + } + } + + static int m(int x) { + return x; + } + + static int x = 200; + boolean y = false; +} diff --git a/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java b/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java index d07f2f93fa0..510f65d5da3 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java +++ b/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java @@ -26,7 +26,7 @@ * @bug 4530538 * @summary Basic unit test of MemoryMXBean.getMemoryPools() and * MemoryMXBean.getMemoryManager(). - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" & !vm.gc.G1 * @author Mandy Chung * * @modules jdk.management @@ -45,6 +45,18 @@ * @run main MemoryTest 2 1 */ +/* + * @test + * @bug 4530538 + * @summary Basic unit test of MemoryMXBean.getMemoryPools() and + * MemoryMXBean.getMemoryManager(). + * @requires vm.gc.G1 + * @author Mandy Chung + * + * @modules jdk.management + * @run main MemoryTest 3 3 + */ + /* * NOTE: This expected result is hardcoded in this test and this test * will be affected if the heap memory layout is changed in diff --git a/test/jdk/java/lang/module/ModuleDescriptorTest.java b/test/jdk/java/lang/module/ModuleDescriptorTest.java index 93c40ac51b6..02c5d473d96 100644 --- a/test/jdk/java/lang/module/ModuleDescriptorTest.java +++ b/test/jdk/java/lang/module/ModuleDescriptorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,6 +23,7 @@ /** * @test + * @bug 8142968 8158456 8298875 * @modules java.base/jdk.internal.access * java.base/jdk.internal.module * @run testng ModuleDescriptorTest @@ -63,6 +64,7 @@ @Test public class ModuleDescriptorTest { + private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); @DataProvider(name = "invalidNames") public Object[][] invalidNames() { @@ -1084,7 +1086,6 @@ public void testUnparseableCompiledVersion(String vs1, String vs2) { } private ModuleDescriptor newModule(String name, String vs) { - JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); Builder builder = JLMA.newModuleBuilder(name, false, Set.of()); if (vs != null) builder.version(vs); @@ -1094,7 +1095,6 @@ private ModuleDescriptor newModule(String name, String vs) { } private Requires newRequires(String name, String vs) { - JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); Builder builder = JLMA.newModuleBuilder("foo", false, Set.of()); if (vs == null) { builder.requires(name); @@ -1361,7 +1361,6 @@ public void testReadsWithPackageFinder() throws Exception { * Test ModuleDescriptor with a packager finder that doesn't return the * complete set of packages. */ - @Test(expectedExceptions = InvalidModuleDescriptorException.class) public void testReadsWithBadPackageFinder() throws Exception { ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo") .requires("java.base") @@ -1373,7 +1372,8 @@ public void testReadsWithBadPackageFinder() throws Exception { ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); // package finder returns a set that doesn't include p - ModuleDescriptor.read(bb, () -> Set.of("q")); + assertThrows(InvalidModuleDescriptorException.class, + () -> ModuleDescriptor.read(bb, () -> Set.of("q"))); } @Test(expectedExceptions = InvalidModuleDescriptorException.class) @@ -1392,63 +1392,76 @@ public void testReadFromEmptyBuffer() { ModuleDescriptor.read(bb); } - // The requires table for java.base must be 0 length - @Test(expectedExceptions = InvalidModuleDescriptorException.class) + /** + * Test ModuleDescriptor.read reading a module-info for java.base that has a non-0 + * length requires table. + */ public void testReadOfJavaBaseWithRequires() { - ModuleDescriptor descriptor - = ModuleDescriptor.newModule("java.base") + ModuleDescriptor descriptor = ModuleDescriptor.newModule("java.base") .requires("other") .build(); ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor); - ModuleDescriptor.read(bb); + assertThrows(InvalidModuleDescriptorException.class, + () -> ModuleDescriptor.read(bb)); } - // The requires table must have an entry for java.base - @Test(expectedExceptions = InvalidModuleDescriptorException.class) + /** + * Test ModuleDescriptor.read reading a module-info with a zero length requires table + * (no entry for java.base). + */ public void testReadWithEmptyRequires() { - ModuleDescriptor descriptor = SharedSecrets.getJavaLangModuleAccess() - .newModuleBuilder("m1", false, Set.of()).build(); + // use non-strict builder to create module that does not require java.base + ModuleDescriptor descriptor = JLMA.newModuleBuilder("m", false, Set.of()).build(); ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor); - ModuleDescriptor.read(bb); + assertThrows(InvalidModuleDescriptorException.class, + () -> ModuleDescriptor.read(bb)); } - // The requires table must have an entry for java.base - @Test(expectedExceptions = InvalidModuleDescriptorException.class) + /** + * Test ModuleDescriptor.read reading a module-info with a non-zero length requires + * table that does not have entry for java.base. + */ public void testReadWithNoRequiresBase() { - ModuleDescriptor descriptor = SharedSecrets.getJavaLangModuleAccess() - .newModuleBuilder("m1", false, Set.of()).requires("m2").build(); + // use non-strict builder to create module that does not require java.base + ModuleDescriptor descriptor = JLMA.newModuleBuilder("m1", false, Set.of()) + .requires("m2") + .build(); ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor); - ModuleDescriptor.read(bb); + assertThrows(InvalidModuleDescriptorException.class, + () -> ModuleDescriptor.read(bb)); } + /** + * Test ModuleDescriptor.read reading a module-info with a requires entry for + * java.base with the ACC_SYNTHETIC flag set. + */ + public void testReadWithSynethticRequiresBase() { + ModuleDescriptor descriptor = ModuleDescriptor.newModule("m") + .requires(Set.of(SYNTHETIC), "java.base") + .build(); + ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor); + assertThrows(InvalidModuleDescriptorException.class, + () -> ModuleDescriptor.read(bb)); + } + + /** + * Test ModuleDescriptor.read with a null parameter. + */ public void testReadWithNull() throws Exception { Module base = Object.class.getModule(); - try { - ModuleDescriptor.read((InputStream)null); - assertTrue(false); - } catch (NullPointerException expected) { } - + assertThrows(NullPointerException.class, + () -> ModuleDescriptor.read((InputStream) null)); + assertThrows(NullPointerException.class, + () -> ModuleDescriptor.read((ByteBuffer) null)); try (InputStream in = base.getResourceAsStream("module-info.class")) { - try { - ModuleDescriptor.read(in, null); - assertTrue(false); - } catch (NullPointerException expected) { } - } + assertThrows(NullPointerException.class, + () -> ModuleDescriptor.read(in, null)); - try { - ModuleDescriptor.read((ByteBuffer)null); - assertTrue(false); - } catch (NullPointerException expected) { } - - - try (InputStream in = base.getResourceAsStream("module-info.class")) { ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes()); - try { - ModuleDescriptor.read(bb, null); - assertTrue(false); - } catch (NullPointerException expected) { } + assertThrows(NullPointerException.class, + () -> ModuleDescriptor.read(bb, null)); } } diff --git a/test/jdk/java/lang/reflect/IllegalArgumentsTest.java b/test/jdk/java/lang/reflect/IllegalArgumentsTest.java index 0d699485f91..bb9efe29e51 100644 --- a/test/jdk/java/lang/reflect/IllegalArgumentsTest.java +++ b/test/jdk/java/lang/reflect/IllegalArgumentsTest.java @@ -25,7 +25,7 @@ * @test * @bug 8277964 * @summary Test IllegalArgumentException be thrown when an argument is invalid - * @run testng/othervm IllegalArgumentsTest + * @run testng/othervm/timeout=180 IllegalArgumentsTest */ import java.lang.reflect.Constructor; diff --git a/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java b/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java index 86403c3378f..4e263d000a4 100644 --- a/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java +++ b/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -40,7 +40,7 @@ public static void main(String... args) throws Exception { // unnamed module gets access to sun.invoke package (e.g. via --add-exports) new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test(); - Class modulePrivateIntf = Class.forName("sun.net.ProgressListener"); + Class modulePrivateIntf = Class.forName("sun.net.PlatformSocketImpl"); new ProxyModuleMapping(modulePrivateIntf).test(); } diff --git a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java index 243c79d9644..6145f48523d 100644 --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java @@ -191,25 +191,25 @@ public int run(HTTPTestServer server, // Now tries with explicitly setting the default authenticator: it should // be invoked again. // Uncomment the code below when 8169068 is available. -// System.out.println("\nClient: Explicitly setting the default authenticator: " -// + toString(Authenticator.getDefault())); -// HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault()); -// count = authOne.count.get(); -// if (count != expectedIncrement) { -// throw new AssertionError("Authenticator #1 called " + count(count) -// + " expected it to be called " + expected(expectedIncrement)); -// } -// count = authTwo.count.get(); -// if (count != expectedIncrement) { -// throw new AssertionError("Authenticator #2 called " + count(count) -// + " expected it to be called " + expected(expectedIncrement)); -// } -// count = AUTHENTICATOR.count.get(); -// if (count != defaultCount + 2 * expectedIncrement) { -// throw new AssertionError("Default Authenticator called " + count(count) -// + " expected it to be called " -// + expected(defaultCount + 2 * expectedIncrement)); -// } + System.out.println("\nClient: Explicitly setting the default authenticator: " + + toString(Authenticator.getDefault())); + HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault()); + count = authOne.count.get(); + if (count != expectedIncrement) { + throw new AssertionError("Authenticator #1 called " + count(count) + + " expected it to be called " + expected(expectedIncrement)); + } + count = authTwo.count.get(); + if (count != expectedIncrement) { + throw new AssertionError("Authenticator #2 called " + count(count) + + " expected it to be called " + expected(expectedIncrement)); + } + count = AUTHENTICATOR.count.get(); + if (count != defaultCount + 2 * expectedIncrement) { + throw new AssertionError("Default Authenticator called " + count(count) + + " expected it to be called " + + expected(defaultCount + 2 * expectedIncrement)); + } // Now tries to set an authenticator on a connected connection. URL url = url(protocol, server.getAddress(), "/"); @@ -238,16 +238,16 @@ public int run(HTTPTestServer server, + ise); } // Uncomment the code below when 8169068 is available. -// try { -// conn.setAuthenticator(Authenticator.getDefault()); -// throw new RuntimeException("Expected IllegalStateException" -// + " trying to set an authenticator after connect" -// + " not raised."); -// } catch (IllegalStateException ise) { -// System.out.println("Client: caught expected ISE" -// + " trying to set an authenticator after connect: " -// + ise); -// } + try { + conn.setAuthenticator(Authenticator.getDefault()); + throw new RuntimeException("Expected IllegalStateException" + + " trying to set an authenticator after connect" + + " not raised."); + } catch (IllegalStateException ise) { + System.out.println("Client: caught expected ISE" + + " trying to set an authenticator after connect: " + + ise); + } try { conn.setAuthenticator(null); throw new RuntimeException("Expected" @@ -279,7 +279,7 @@ public int run(HTTPTestServer server, // All good! // return the number of times the default authenticator is supposed // to have been called. - return scheme == HttpSchemeType.NONE ? 0 : 1 * EXPECTED_AUTH_CALLS_PER_TEST; + return scheme == HttpSchemeType.NONE ? 0 : 2 * EXPECTED_AUTH_CALLS_PER_TEST; } static String toString(Authenticator a) { diff --git a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java index 4d1f5c52a78..3f436ef6d02 100644 --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java @@ -23,10 +23,12 @@ import java.io.IOException; import java.net.Authenticator; +import java.net.BindException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.time.Duration; import javax.net.ssl.HttpsURLConnection; /** @@ -35,11 +37,39 @@ */ public class HTTPTestClient extends HTTPTest { + public static final long DELAY_BEFORE_RETRY = 2500; // milliseconds + public static void connect(HttpProtocolType protocol, HTTPTestServer server, HttpAuthType authType, Authenticator auth) throws IOException { + try { + doConnect(protocol, server, authType, auth); + } catch (BindException ex) { + // sleep a bit then try again once + System.out.println("WARNING: Unexpected BindException: " + ex); + System.out.println("\tSleeping a bit and try again..."); + long start = System.nanoTime(); + System.gc(); + try { + Thread.sleep(DELAY_BEFORE_RETRY); + } catch (InterruptedException iex) { + // ignore + } + System.gc(); + System.out.println("\tRetrying after " + + Duration.ofNanos(System.nanoTime() - start).toMillis() + + " milliseconds"); + doConnect(protocol, server, authType, auth); + } + } + + public static void doConnect(HttpProtocolType protocol, + HTTPTestServer server, + HttpAuthType authType, + Authenticator auth) + throws IOException { InetSocketAddress address = server.getAddress(); final URL url = url(protocol, address, "/"); diff --git a/test/jdk/java/net/ServerSocket/ImplAccept.java b/test/jdk/java/net/ServerSocket/ImplAccept.java new file mode 100644 index 00000000000..139c2485b55 --- /dev/null +++ b/test/jdk/java/net/ServerSocket/ImplAccept.java @@ -0,0 +1,293 @@ +/* + * 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 + * @bug 8278326 + * @modules java.base/java.net:+open + * @run junit ImplAccept + * @summary Test ServerSocket.implAccept with a Socket in different states. + */ + +import java.io.FileDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketImpl; +import java.net.SocketOption; +import java.net.StandardSocketOptions; +import java.io.IOException; + +import org.junit.*; +import static org.junit.jupiter.api.Assertions.*; + +public class ImplAccept { + + /** + * Test ServerSocket.implAccept with an unbound Socket. + */ + @Test + public void testUnbound() throws Exception { + try (Socket socket = new Socket()) { + + // Socket.impl -> DelegatingSocketImpl + SocketImpl si = getSocketImpl(socket); + assertTrue(isDelegatingSocketImpl(si)); + + try (ServerSocket ss = serverSocketToAccept(socket); + Socket peer = new Socket(ss.getInetAddress(), ss.getLocalPort())) { + + Socket s = ss.accept(); + assertTrue(s == socket); + + // Socket.impl should be replaced with a new PlatformSocketImpl + SocketImpl psi = getSocketImpl(socket); + assertTrue(isPlatformSocketImpl(psi)); + + // socket and peer should be connected to each other + pingPong(socket, peer); + } + } + } + + /** + * Test ServerSocket.implAccept with a bound Socket. The usage is nonsensical + * but we can test that the accepted Socket is connected and the underlying + * socket from the original SocketImpl is closed. + */ + @Test + public void testBound() throws Exception { + try (Socket socket = new Socket()) { + + // Socket.impl -> DelegatingSocketImpl -> PlatformSocketImpl + SocketImpl si = getSocketImpl(socket); + SocketImpl psi1 = getDelegate(si); + assertTrue(isPlatformSocketImpl(psi1)); + + // bind to local address + socket.bind(loopbackSocketAddress()); + assertTrue(isSocketOpen(psi1)); + + try (ServerSocket ss = serverSocketToAccept(socket); + Socket peer = new Socket(ss.getInetAddress(), ss.getLocalPort())) { + + Socket s = ss.accept(); + assertTrue(s == socket); + + // Socket.impl should be replaced with a new PlatformSocketImpl + SocketImpl psi2 = getSocketImpl(socket); + assertTrue(isPlatformSocketImpl(psi2)); + + // psi1 should be closed + assertFalse(isSocketOpen(psi1)); + + // socket and peer should be connected to each other + pingPong(socket, peer); + } + } + } + + /** + * Test ServerSocket.implAccept with a connected Socket. The usage is nonsensical + * but we can test that the accepted Socket is connected and the underlying + * socket from the original SocketImpl is closed. + */ + @Test + public void testConnected() throws Exception { + Socket socket; + Socket peer1; + try (ServerSocket ss = new ServerSocket()) { + ss.bind(loopbackSocketAddress()); + socket = new Socket(ss.getInetAddress(), ss.getLocalPort()); + peer1 = ss.accept(); + } + + try { + // Socket.impl -> DelegatingSocketImpl -> PlatformSocketImpl + SocketImpl si = getSocketImpl(socket); + SocketImpl psi1 = getDelegate(si); + assertTrue(isPlatformSocketImpl(psi1)); + + try (ServerSocket ss = serverSocketToAccept(socket); + Socket peer2 = new Socket(ss.getInetAddress(), ss.getLocalPort())) { + + Socket s = ss.accept(); + assertTrue(s == socket); + + // Socket.impl should be replaced with a new PlatformSocketImpl + SocketImpl psi2 = getSocketImpl(socket); + assertTrue(isPlatformSocketImpl(psi2)); + + // psi1 should be closed and peer1 should read EOF + assertFalse(isSocketOpen(psi1)); + assertTrue(peer1.getInputStream().read() == -1); + + // socket and peer2 should be connected to each other + pingPong(socket, peer2); + } + } finally { + socket.close(); + peer1.close(); + } + } + + /** + * Test ServerSocket.implAccept with a closed Socket. The usage is nonsensical + * but we can test ServerSocket.accept throws and that it closes the connection + * to the peer. + */ + @Test + public void testClosed() throws Exception { + Socket socket = new Socket(); + socket.close(); + + try (ServerSocket ss = serverSocketToAccept(socket); + Socket peer = new Socket(ss.getInetAddress(), ss.getLocalPort())) { + + SocketImpl si = getSocketImpl(socket); + + // accept should throw and peer should read EOF + assertThrows(IOException.class, ss::accept); + assertTrue(peer.getInputStream().read() == -1); + + // the SocketImpl should have not changed + assertTrue(getSocketImpl(socket) == si); + } + } + + /** + * Returns the socket's SocketImpl. + */ + private static SocketImpl getSocketImpl(Socket s) { + try { + Field f = Socket.class.getDeclaredField("impl"); + f.setAccessible(true); + return (SocketImpl) f.get(s); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the SocketImpl that the given SocketImpl delegates to. + */ + private static SocketImpl getDelegate(SocketImpl si) { + try { + Class clazz = Class.forName("java.net.DelegatingSocketImpl"); + Field f = clazz.getDeclaredField("delegate"); + f.setAccessible(true); + return (SocketImpl) f.get(si); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns true if the SocketImpl is a DelegatingSocketImpl. + */ + private static boolean isDelegatingSocketImpl(SocketImpl si) { + try { + Class clazz = Class.forName("java.net.DelegatingSocketImpl"); + return clazz.isInstance(si); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns true if the SocketImpl is a PlatformSocketImpl. + */ + private static boolean isPlatformSocketImpl(SocketImpl si) { + try { + Class clazz = Class.forName("sun.net.PlatformSocketImpl"); + return clazz.isInstance(si); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns true if the SocketImpl has an open socket. + */ + private static boolean isSocketOpen(SocketImpl si) throws Exception { + assertTrue(isPlatformSocketImpl(si)); + + // check if SocketImpl.fd is set + Field f = SocketImpl.class.getDeclaredField("fd"); + f.setAccessible(true); + FileDescriptor fd = (FileDescriptor) f.get(si); + if (fd == null) { + return false; // not created + } + + // call getOption to get the value of the SO_REUSEADDR socket option + Method m = SocketImpl.class.getDeclaredMethod("getOption", SocketOption.class); + m.setAccessible(true); + try { + m.invoke(si, StandardSocketOptions.SO_REUSEADDR); + return true; // socket is open + } catch (InvocationTargetException e) { + if (e.getCause() instanceof IOException) { + return false; // assume socket is closed + } + throw e; + } + } + + /** + * Test that two sockets are connected to each other. + */ + private static void pingPong(Socket s1, Socket s2) throws Exception { + s1.getOutputStream().write(11); + s2.getOutputStream().write(22); + assertTrue(s1.getInputStream().read() == 22); + assertTrue(s2.getInputStream().read() == 11); + } + + /** + * Creates a ServerSocket that returns the given Socket from accept. + */ + private static ServerSocket serverSocketToAccept(Socket s) throws IOException { + ServerSocket ss = new ServerSocket() { + @Override + public Socket accept() throws IOException { + implAccept(s); + return s; + } + }; + ss.bind(loopbackSocketAddress()); + return ss; + } + + /** + * Returns a new InetSocketAddress with the loopback interface and port 0. + */ + private static InetSocketAddress loopbackSocketAddress() { + InetAddress loopback = InetAddress.getLoopbackAddress(); + return new InetSocketAddress(loopback, 0); + } +} diff --git a/test/jdk/java/net/Socket/asyncClose/Leaky.java b/test/jdk/java/net/Socket/asyncClose/Leaky.java new file mode 100644 index 00000000000..48ed6a7e91f --- /dev/null +++ b/test/jdk/java/net/Socket/asyncClose/Leaky.java @@ -0,0 +1,244 @@ +/* + * 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 + * @bug 8278326 + * @modules java.base/java.net:+open + * @run junit Leaky + * @summary Test async close when binding, connecting, or reading a socket option + */ + +import java.io.FileDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketImpl; +import java.net.SocketOption; +import java.net.StandardSocketOptions; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +import org.junit.*; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class Leaky { + private static ScheduledExecutorService executor; + private static ServerSocket listener; + + @BeforeAll + public static void setup() throws Exception { + listener = new ServerSocket(); + listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + executor = Executors.newScheduledThreadPool(2); + } + + @AfterAll + public static void finish() throws Exception { + executor.close(); + listener.close(); + } + + /** + * Race Socket bind and close. + */ + @RepeatedTest(100) + public void raceBindAndClose() throws Exception { + Socket socket = new Socket(); + + race(socket::close, () -> { + try { + socket.bind(new InetSocketAddress(0)); + } catch (IOException ioe) { + if (!socket.isClosed()) { + throw ioe; + } + } + }); + + // check that there isn't an open socket + SocketImpl psi = getPlatformSocketImpl(socket); + assertFalse(isSocketOpen(psi)); + } + + /** + * Race Socket connect and close. + */ + @RepeatedTest(100) + public void raceConnectAndClose() throws Exception { + Socket socket = new Socket(); + + race(socket::close, () -> { + try { + socket.connect(listener.getLocalSocketAddress()); + // if connected, need to close other end + listener.accept().close(); + } catch (IOException ioe) { + if (!socket.isClosed()) { + throw ioe; + } + } + }); + + // check that there isn't an open socket + SocketImpl psi = getPlatformSocketImpl(socket); + assertFalse(isSocketOpen(psi)); + } + + /** + * Race Socket getOption and close. + */ + @RepeatedTest(100) + public void raceGetOptionAndClose() throws Exception { + Socket socket = new Socket(); + + race(socket::close, () -> { + try { + socket.getOption(StandardSocketOptions.SO_REUSEADDR); + } catch (IOException ioe) { + if (!socket.isClosed()) { + throw ioe; + } + } + }); + + // check that there isn't an open socket + SocketImpl psi = getPlatformSocketImpl(socket); + assertFalse(isSocketOpen(psi)); + } + + /** + * A task that may throw an exception. + */ + private interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * Staggers two tasks to execute after random delays. + */ + private void race(ThrowingRunnable task1, ThrowingRunnable task2) throws Exception { + int delay1 = ThreadLocalRandom.current().nextInt(10); + int delay2 = ThreadLocalRandom.current().nextInt(10); + + Future future1 = executor.schedule(() -> { + task1.run(); + return null; + }, delay1, TimeUnit.MILLISECONDS); + + Future future2 = executor.schedule(() -> { + task2.run(); + return null; + }, delay2, TimeUnit.MILLISECONDS); + + ExecutionException e = null; + try { + future1.get(); + } catch (ExecutionException e1) { + e = e1; + } + try { + future2.get(); + } catch (ExecutionException e2) { + if (e == null) { + e = e2; + } else { + e.addSuppressed(e2); + } + } + if (e != null) { + throw e; + } + } + + /** + * Return the underlying PlatformSocketImpl for the given socket. + */ + private static SocketImpl getPlatformSocketImpl(Socket s) { + SocketImpl si = getSocketImpl(s); + return getDelegate(si); + } + + /** + * Returns the socket's SocketImpl. + */ + private static SocketImpl getSocketImpl(Socket s) { + try { + Field f = Socket.class.getDeclaredField("impl"); + f.setAccessible(true); + return (SocketImpl) f.get(s); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the SocketImpl that the given SocketImpl delegates to. + */ + private static SocketImpl getDelegate(SocketImpl si) { + try { + Class clazz = Class.forName("java.net.DelegatingSocketImpl"); + Field f = clazz.getDeclaredField("delegate"); + f.setAccessible(true); + return (SocketImpl) f.get(si); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns true if the SocketImpl has an open socket. + */ + private static boolean isSocketOpen(SocketImpl si) throws Exception { + // check if SocketImpl.fd is set + Field f = SocketImpl.class.getDeclaredField("fd"); + f.setAccessible(true); + FileDescriptor fd = (FileDescriptor) f.get(si); + if (fd == null) { + return false; // not created + } + + // call getOption to get the value of the SO_REUSEADDR socket option + Method m = SocketImpl.class.getDeclaredMethod("getOption", SocketOption.class); + m.setAccessible(true); + try { + m.invoke(si, StandardSocketOptions.SO_REUSEADDR); + return true; // socket is open + } catch (InvocationTargetException e) { + if (e.getCause() instanceof IOException) { + return false; // assume socket is closed + } + throw e; + } + } +} diff --git a/test/jdk/java/net/URI/Test.java b/test/jdk/java/net/URI/Test.java index f48c8d84dc9..00d473f87be 100644 --- a/test/jdk/java/net/URI/Test.java +++ b/test/jdk/java/net/URI/Test.java @@ -24,7 +24,7 @@ /* @test * @summary Unit test for java.net.URI * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 - * 7171415 6339649 6933879 8037396 8272072 8051627 + * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 * @author Mark Reinhold */ @@ -1619,6 +1619,53 @@ static void bugs() { b8037396(); b8051627(); b8272072(); + b8297687(); + } + + private static void b8297687() { + // constructors that take a hostname should fail + test("ftps", "p.e.local|SIT@p.e.local", "/path", null) + .x().z(); + test("ftps", null,"p.e.local|SIT@p.e.local", -1, "/path", null, null) + .x().z(); + // constructors that take an authority component should succeed + test("ftps", "p.e.local|SIT@p.e.local", "/path", null,null) + .s("ftps") + .sp("//p.e.local%7CSIT@p.e.local/path") + .spd("//p.e.local|SIT@p.e.local/path") + .u("p.e.local%7CSIT") + .ud("p.e.local|SIT") + .h("p.e.local") + .n(-1) + .p("/path") + .pd("/path") + .z(); + + // check index in exception for constructors that should fail + try { + URI uri = new URI("ftps", "p.e.local|SIT@p.e.local", "/path", null); + throw new AssertionError("Expected URISyntaxException not thrown for " + uri); + } catch (URISyntaxException ex) { + if (ex.getMessage().contains("at index 16")) { + System.out.println("Got expected exception: " + ex); + } else { + throw new AssertionError("Exception does not point at index 16", ex); + } + } + testCount++; + + // check index in exception for constructors that should fail + try { + URI uri = new URI("ftps", null, "p.e.local|SIT@p.e.local", -1, "/path", null, null); + throw new AssertionError("Expected URISyntaxException not thrown for " + uri); + } catch (URISyntaxException ex) { + if (ex.getMessage().contains("at index 16")) { + System.out.println("Got expected exception: " + ex); + } else { + throw new AssertionError("Exception does not point at index 16", ex); + } + } + testCount++; } // 6339649 - include detail message from nested exception diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java index 0768ddb7aab..c134f3cd99d 100644 --- a/test/jdk/java/net/httpclient/CancelRequestTest.java +++ b/test/jdk/java/net/httpclient/CancelRequestTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8245462 8229822 8254786 8297075 8297149 + * @bug 8245462 8229822 8254786 8297075 8297149 8298340 * @summary Tests cancelling the request. * @library /test/lib http2/server * @key randomness diff --git a/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java b/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java index 8bc490a92e7..bceb3e7ca1e 100644 --- a/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java +++ b/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java @@ -104,6 +104,7 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { static final long SERVER_LATENCY = 75; static final int ITERATION_COUNT = 3; + static final long CLIENT_SHUTDOWN_GRACE_DELAY = 1500; // milliseconds // a shared executor helps reduce the amount of threads created by the test static final Executor executor = new TestExecutor(Executors.newCachedThreadPool()); static final ConcurrentMap FAILURES = new ConcurrentHashMap<>(); @@ -287,7 +288,7 @@ public void testAsLines(String uri, boolean sameClient) if (sameClient) continue; client = null; System.gc(); - var error = TRACKER.check(tracker, 500); + var error = TRACKER.check(tracker, CLIENT_SHUTDOWN_GRACE_DELAY); if (error != null) throw error; } } @@ -329,7 +330,7 @@ public void testInputStream(String uri, boolean sameClient) if (sameClient) continue; client = null; System.gc(); - var error = TRACKER.check(tracker, 1); + var error = TRACKER.check(tracker, CLIENT_SHUTDOWN_GRACE_DELAY); if (error != null) throw error; } } diff --git a/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java new file mode 100644 index 00000000000..6468175ab59 --- /dev/null +++ b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 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 8294047 + * @library /test/lib + * @run junit HttpResponseInputStreamInterruptTest + */ + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.concurrent.CountDownLatch; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class HttpResponseInputStreamInterruptTest { + + HttpServer server; + int port; + private final CountDownLatch interruptReadyLatch = new CountDownLatch(2); + private final CountDownLatch interruptDoneLatch = new CountDownLatch(1); + static final String FIRST_MESSAGE = "Should be received"; + static final String SECOND_MESSAGE = "Shouldn't be received"; + + @BeforeAll + void before() throws Exception { + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress addr = new InetSocketAddress(loopback, 0); + server = HttpServer.create(addr, 0); + port = server.getAddress().getPort(); + Handler handler = new Handler(interruptReadyLatch, interruptDoneLatch); + server.createContext("/HttpResponseInputStreamInterruptTest/", handler); + server.start(); + } + + @AfterAll + void after() throws Exception { + server.stop(0); + } + + @Test + public void test() throws Exception { + // create client and interrupter threads + Thread clientThread = createClientThread(interruptReadyLatch, port); + Thread interrupterThread = new Thread(() -> { + try { + // wait until the clientThread is just about to read the second message sent by the server + // then interrupt the thread to cause an error to be thrown + interruptReadyLatch.await(); + clientThread.interrupt(); + interruptDoneLatch.countDown(); + } catch (InterruptedException e) { + System.out.println("interrupterThread failed"); + throw new RuntimeException(e); + } + }); + + // Start the threads then wait until clientThread completes + clientThread.start(); + interrupterThread.start(); + clientThread.join(); + } + + static class Handler implements HttpHandler { + + CountDownLatch interruptReadyLatch; + CountDownLatch interruptDoneLatch; + + public Handler(CountDownLatch interruptReadyLatch, CountDownLatch interruptDoneLatch) { + this.interruptReadyLatch = interruptReadyLatch; + this.interruptDoneLatch = interruptDoneLatch; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try (OutputStream os = exchange.getResponseBody()) { + byte[] workingResponse = FIRST_MESSAGE.getBytes(); + byte[] errorResponse = SECOND_MESSAGE.getBytes(); + exchange.sendResponseHeaders(200, workingResponse.length + errorResponse.length); + + // write and flush the first message which is expected to be received successfully + os.write(workingResponse); + os.flush(); + + // await the interrupt threads completion, then write the second message + interruptReadyLatch.countDown(); + interruptDoneLatch.await(); + os.write(errorResponse); + } catch (InterruptedException e) { + System.out.println("interruptDoneLatch await failed"); + throw new RuntimeException(e); + } + } + } + + static Thread createClientThread(CountDownLatch interruptReadyLatch, int port) { + return new Thread(() -> { + try { + HttpClient client = HttpClient + .newBuilder() + .proxy(HttpClient.Builder.NO_PROXY) + .build(); + + URI uri = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .path("/HttpResponseInputStreamInterruptTest/") + .build(); + + HttpRequest request = HttpRequest + .newBuilder(uri) + .GET() + .build(); + + // Send a httpRequest and assert the first response is received as expected + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); + String firstOutput = new String(response.body().readNBytes(FIRST_MESSAGE.getBytes().length)); + assertEquals(firstOutput, FIRST_MESSAGE); + + // countdown on latch, and assert that an IOException is throw due to the interrupt + // and assert that the cause is a InterruptedException + interruptReadyLatch.countDown(); + var thrown = assertThrows(IOException.class, () -> response.body().readAllBytes(), "expected IOException"); + var cause = thrown.getCause(); + assertTrue(cause instanceof InterruptedException, cause + " is not an InterruptedException"); + var thread = Thread.currentThread(); + assertTrue(thread.isInterrupted(), "Thread " + thread + " is not interrupted"); + } catch (Throwable t) { + t.printStackTrace(); + fail(); + } + }); + } +} diff --git a/test/jdk/java/net/httpclient/ISO_8859_1_Test.java b/test/jdk/java/net/httpclient/ISO_8859_1_Test.java index f947d886dbc..9be5269f5f1 100644 --- a/test/jdk/java/net/httpclient/ISO_8859_1_Test.java +++ b/test/jdk/java/net/httpclient/ISO_8859_1_Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -447,7 +447,7 @@ public void teardown() throws Exception { sharedClient == null ? null : sharedClient.toString(); sharedClient = null; Thread.sleep(100); - AssertionError fail = TRACKER.check(500); + AssertionError fail = TRACKER.check(1500); try { http1TestServer.stop(); https1TestServer.stop(); diff --git a/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java b/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java index c5f6d906983..7f361b8cf52 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java +++ b/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8237470 + * @bug 8237470 8299015 * @summary Confirm HttpResponse.BodySubscribers#ofFile(Path) * works with default and non-default file systems * when SecurityManager is enabled @@ -66,11 +66,15 @@ import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.BodySubscriber; import java.net.http.HttpResponse.BodySubscribers; +import java.nio.Buffer; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Map; +import java.util.concurrent.Flow; +import java.util.stream.IntStream; import static java.lang.System.out; import static java.net.http.HttpClient.Builder.NO_PROXY; @@ -199,6 +203,30 @@ private void receive(String uriString, } } + // A large enough number of buffers to gather from, in an attempt to provoke a partial + // write. Loosely based on the value of _SC_IOV_MAX, to trigger partial gathering write. + private static final int NUM_GATHERING_BUFFERS = 1024 + 1; + + @Test + public void testSubscribersWritesAllBytes() throws Exception { + var buffers = IntStream.range(0, NUM_GATHERING_BUFFERS) + .mapToObj(i -> new byte[10]) + .map(ByteBuffer::wrap).toList(); + int expectedSize = buffers.stream().mapToInt(Buffer::remaining).sum(); + + var subscriber = BodySubscribers.ofFile(defaultFsPath); + subscriber.onSubscribe(new Flow.Subscription() { + @Override + public void request(long n) { } + @Override + public void cancel() { } + }); + subscriber.onNext(buffers); + subscriber.onComplete(); + buffers.forEach(b -> assertEquals(b.remaining(), 0) ); + assertEquals(expectedSize, Files.size(defaultFsPath)); + } + @BeforeTest public void setup() throws Exception { sslContext = new SimpleSSLContext().get(); diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index 669f20cd88c..e07badd2bb7 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -331,8 +331,10 @@ public void init() { // check authorization credentials, if required by the server if (credentials != null) { if (!authorized(credentials, headers)) { + boolean shouldClose = shouldCloseAfter407(headers); + var closestr = shouldClose ? "Connection: close\r\n" : ""; String resp = "HTTP/1.1 407 Proxy Authentication Required\r\n" + - "Content-Length: 0\r\n" + + "Content-Length: 0\r\n" + closestr + "Proxy-Authenticate: Basic realm=\"proxy realm\"\r\n\r\n"; clientSocket.setOption(StandardSocketOptions.TCP_NODELAY, true); clientSocket.setOption(StandardSocketOptions.SO_LINGER, 2); @@ -344,7 +346,7 @@ public void init() { System.out.printf("Proxy: unauthorized; 407 sent (%s/%s), linger: %s, nodelay: %s%n", buffer.position(), buffer.position() + buffer.remaining(), linger, nodelay); } - if (shouldCloseAfter407(headers)) { + if (shouldClose) { closeConnection(); return; } @@ -445,6 +447,11 @@ void closeConnection() throws IOException { // If the client sends a request body we will need to close the connection // otherwise, we can keep it open. private boolean shouldCloseAfter407(List headers) throws IOException { + var cmdline = headers.get(0); + int m = cmdline.indexOf(' '); + var method = (m > 0) ? cmdline.substring(0, m) : null; + var nobody = List.of("GET", "HEAD"); + var te = findFirst(headers, "transfer-encoding"); if (te != null) { // processing transfer encoding not implemented @@ -455,28 +462,37 @@ private boolean shouldCloseAfter407(List headers) throws IOException { } var cl = findFirst(headers, "content-length"); int n = -1; - try { - n = Integer.parseInt(cl); - if (debug) { - System.out.printf("Proxy: content-length: %d%n", cl); + if (cl == null) { + if (nobody.contains(method)) { + n = 0; + System.out.printf("Proxy: no content length for %s, assuming 0%n", method); + } else { + System.out.printf("Proxy: no content-length for %s, closing connection%n", method); + return true; } - } catch (IllegalFormatException x) { - if (debug) { - System.out.println("Proxy: bad content-length, closing connection"); + } else { + try { + n = Integer.parseInt(cl); + if (debug) { + System.out.printf("Proxy: content-length: %d%n", n); + } + } catch (NumberFormatException x) { + if (debug) { + System.out.println("Proxy: bad content-length, closing connection"); + System.out.println("Proxy: \tcontent-length: " + cl); + System.out.println("Proxy: \theaders: " + headers); + System.out.println("Proxy: \t" + x); + } + return true; // should close } - return true; // should close } - if (n > 0 || n < -1) { + if (n > 0) { if (debug) { System.out.println("Proxy: request body with 407, closing connection"); } return true; // should close } - var cmdline = headers.get(0); - int m = cmdline.indexOf(' '); - var method = (m > 0) ? cmdline.substring(0, m) : null; - var nobody = List.of("GET", "HEAD"); - if (n == 0 || nobody.contains(m)) { + if (n == 0) { var available = clientIn.available(); var drained = drain(clientSocket); if (drained > 0 || available > 0) { diff --git a/test/jdk/java/net/httpclient/ReferenceTracker.java b/test/jdk/java/net/httpclient/ReferenceTracker.java index 32734deea47..ae55f969c71 100644 --- a/test/jdk/java/net/httpclient/ReferenceTracker.java +++ b/test/jdk/java/net/httpclient/ReferenceTracker.java @@ -214,12 +214,15 @@ public AssertionError check(Tracker tracker, long waitStart = System.nanoTime(); long waited = 0; long toWait = Math.min(graceDelayMs, Math.max(delay, 1)); - for (int i = 0; i < count; i++) { + int i = 0; + for (i = 0; i < count; i++) { if (hasOutstanding.test(tracker)) { System.gc(); try { if (i == 0) { System.out.println("Waiting for HTTP operations to terminate..."); + System.out.println("\tgracedelay: " + graceDelayMs + + " ms, iterations: " + count + ", wait/iteration: " + toWait + "ms"); } waited += toWait; Thread.sleep(toWait); @@ -250,7 +253,8 @@ public AssertionError check(Tracker tracker, printThreads(msg, System.err); } System.out.println("AssertionError: Found some " + description + " in " - + tracker.getName() + " after " + duration + " ms, waited " + waited + " ms"); + + tracker.getName() + " after " + i + " iterations and " + duration + + " ms, waited " + waited + " ms"); } return fail; } @@ -261,21 +265,34 @@ public AssertionError check(long graceDelayMs, boolean printThreads) { AssertionError fail = null; graceDelayMs = Math.max(graceDelayMs, 100); + long waitStart = System.nanoTime(); long delay = Math.min(graceDelayMs, 10); + long toWait = Math.min(graceDelayMs, Math.max(delay, 1)); + long waited = 0; var count = delay > 0 ? graceDelayMs / delay : 1; - for (int i = 0; i < count; i++) { + int i = 0; + for (i = 0; i < count; i++) { if (TRACKERS.stream().anyMatch(hasOutstanding)) { System.gc(); try { if (i == 0) { System.out.println("Waiting for HTTP operations to terminate..."); + System.out.println("\tgracedelay: " + graceDelayMs + + " ms, iterations: " + count + ", wait/iteration: " + toWait + "ms"); } - Thread.sleep(Math.min(graceDelayMs, Math.max(delay, 1))); + waited += toWait; + Thread.sleep(toWait); } catch (InterruptedException x) { // OK } - } else break; + } else { + System.out.println("No outstanding HTTP operations remaining after " + + i + "/" + count + " iterations and " + waited + "/" + graceDelayMs + + " ms, (wait/iteration " + toWait + " ms)"); + break; + } } + long duration = Duration.ofNanos(System.nanoTime() - waitStart).toMillis(); if (TRACKERS.stream().anyMatch(hasOutstanding)) { StringBuilder warnings = diagnose(new StringBuilder(), hasOutstanding); addSummary(warnings); @@ -284,7 +301,7 @@ public AssertionError check(long graceDelayMs, } } else { System.out.println("PASSED: No " + description + " found in " - + getTrackedClientCount() + " clients"); + + getTrackedClientCount() + " clients in " + duration + " ms"); } if (fail != null) { Predicate isAlive = Tracker::isSelectorAlive; @@ -292,6 +309,9 @@ public AssertionError check(long graceDelayMs, printThreads("Some selector manager threads are still alive: ", System.out); printThreads("Some selector manager threads are still alive: ", System.err); } + System.out.println("AssertionError: Found some " + description + " in " + + getTrackedClientCount() + " clients after " + i + " iterations and " + duration + + " ms, waited " + waited + " ms"); } return fail; } diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java deleted file mode 100644 index 520c16de9a8..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublisher; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersConcat - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersConcat() { - super(new TestEnvironment(450L)); - } - - private static BodyPublisher ofByteArrays(int n, byte[] bytes) { - return BodyPublishers.ofByteArrays(Collections.nCopies((int) n, bytes)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - System.out.println("BodyPublishersConcat: %d elements requested" - .formatted(nElements)); - byte[] bytes = S.arrayOfNRandomBytes(ELEMENT_SIZE); - if (nElements == 0) { - System.out.println("BodyPublishersConcat: empty publisher"); - return BodyPublishers.concat(); - } else if (nElements == 1) { - System.out.println("BodyPublishersConcat: singleton publisher"); - return BodyPublishers.concat(ofByteArrays(1, bytes)); - } else if (nElements < 4) { - int left = (int)nElements/2; - int right = (int)nElements - left; - System.out.println("BodyPublishersConcat: dual publisher (%d, %d)".formatted(left, right)); - return BodyPublishers.concat(ofByteArrays(left, bytes), - ofByteArrays(right, bytes)); - } else { - List publishers = new ArrayList<>(); - List sizes = new ArrayList<>(); - long remaining = nElements; - int max = (int) Math.min((long)Integer.MAX_VALUE, nElements/2L); - while (remaining > 0) { - int length = S.randomIntUpTo(max); - if (length == 0) length = 1; - sizes.add(length); - if (remaining > length) { - publishers.add(ofByteArrays(length, bytes)); - remaining = remaining - length; - } else { - publishers.add(ofByteArrays((int)remaining, bytes)); - remaining = 0; - } - } - System.out.println("BodyPublishersConcat: multi publisher " + sizes); - return BodyPublishers.concat(publishers.toArray(BodyPublisher[]::new)); - } - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java deleted file mode 100644 index b997fa6a7fc..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; -import java.util.stream.Stream; - -/* See TckDriver.java for more information */ -public class BodyPublishersFromPublisher - extends FlowPublisherVerification { - - public BodyPublishersFromPublisher() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - Stream buffers = - Stream.generate(() -> S.bufferOfNRandomBytes(1024)) - .limit(nElements); - Publisher pub = S.publisherOfStream(buffers); - return BodyPublishers.fromPublisher(pub); - } - - @Override - public Publisher createFailedFlowPublisher() { - return BodyPublishers.fromPublisher(S.newErroredPublisher()); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java deleted file mode 100644 index 97b30f4511d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.atomic.AtomicLong; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfFile - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - private static final AtomicLong UNIQUE_NUMBERS = new AtomicLong(); - - public BodyPublishersOfFile() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - try { - Path f = createFile(nElements * ELEMENT_SIZE); - return BodyPublishers.ofFile(f); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private static Path createFile(long nBytes) throws IOException { - String name = "f" + UNIQUE_NUMBERS.getAndIncrement(); - Path f = Files.createFile(Path.of(name)); - return Files.write(f, S.arrayOfNRandomBytes(nBytes)); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java deleted file mode 100644 index e0209fe058c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfSubByteArray - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersOfSubByteArray() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - int prefixLen = S.randomIntUpTo(13); - int postfixLen = S.randomIntUpTo(17); - byte[] b = S.arrayOfNRandomBytes(nElements * ELEMENT_SIZE); - byte[] contents = new byte[prefixLen + b.length + postfixLen]; - System.arraycopy(b, 0, contents, prefixLen, b.length); - return BodyPublishers.ofByteArray(contents, prefixLen, b.length); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java deleted file mode 100644 index 1fbfc5f6717..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersFromLineSubscriber - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersFromLineSubscriber() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.fromLineSubscriber( - S.nonCompliantSubscriber()); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java deleted file mode 100644 index ca1256cf91c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersFromSubscriber - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersFromSubscriber() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - Subscriber> sub = S.nonCompliantSubscriber(); - return BodySubscribers.fromSubscriber(sub); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java deleted file mode 100644 index 0fa2ad0b14c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersMapping - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersMapping() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.mapping(BodySubscribers.ofByteArray(), - bytes -> bytes.length); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java deleted file mode 100644 index 0dfbdf8eb1a..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfByteArrayConsumer - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfByteArrayConsumer() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofByteArrayConsumer(bytes -> { }); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java deleted file mode 100644 index 76a06dfc171..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfFile - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfFile() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofFile(Path.of("f1.bin")); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java deleted file mode 100644 index b3330d976b1..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfInputStream - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfInputStream() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofInputStream(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java deleted file mode 100644 index 4933804631a..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfLines - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfLines() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofLines(StandardCharsets.UTF_8); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java deleted file mode 100644 index 9b274b543e5..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisher - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfPublisher() { - super(new TestEnvironment(450L)); - } - - /* The reason for overriding this method is that BodySubscribers.ofPublisher - is somewhat tricky. It is not an independent Subscriber, but rather - an adaptor from Subscriber to Publisher. Until the Subscriber that - subscribed to that resulting Publisher requests anything, nothing - happens. */ - @Override - public void triggerFlowRequest( - Subscriber> subscriber) - { - BodySubscriber>> sub = - (BodySubscriber>>) subscriber; - CompletionStage>> body = sub.getBody(); - Publisher> pub = body.toCompletableFuture().join(); - pub.subscribe(new Subscriber<>() { - - @Override - public void onSubscribe(Subscription subscription) { - subscription.request(Integer.MAX_VALUE); - } - - @Override public void onNext(List item) { } - @Override public void onError(Throwable throwable) { } - @Override public void onComplete() { } - }); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofPublisher(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java deleted file mode 100644 index ef2b4e98f2b..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisher1 - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfPublisher1() { - super(new TestEnvironment(450L)); - } - - /* The reason for overriding this method is that BodySubscribers.ofPublisher - is somewhat tricky. It is not an independent Subscriber, but rather - an adaptor from Subscriber to Publisher. Until the Subscriber that - subscribed to that resulting Publisher requests anything, nothing - happens. */ - @Override - public void triggerFlowRequest( - Subscriber> subscriber) - { - BodySubscriber>> sub = - (BodySubscriber>>) subscriber; - CompletionStage>> body = sub.getBody(); - Publisher> pub = body.toCompletableFuture().join(); - pub.subscribe(new Subscriber<>() { - - Subscription sub; - - @Override - public void onSubscribe(Subscription subscription) { - (sub = subscription).request(1); - } - - @Override public void onNext(List item) { - sub.request(1); - } - - @Override public void onError(Throwable throwable) { } - @Override public void onComplete() { } - }); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofPublisher(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java deleted file mode 100644 index 1d8d7aee095..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Publisher; -import java.util.stream.Stream; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisherPublisher - extends FlowPublisherVerification> { - - public BodySubscribersOfPublisherPublisher() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher> createFlowPublisher(long nElements) { - BodySubscriber>> sub = - BodySubscribers.ofPublisher(); - Stream> buffers = - Stream.generate(() -> S.listOfBuffersFromBufferOfNBytes(1024)) - .limit(nElements); - Publisher> pub = S.publisherOfStream(buffers); - pub.subscribe(sub); - return sub.getBody().toCompletableFuture().join(); - } - - @Override - public Publisher> createFailedFlowPublisher() { - BodySubscriber>> sub = - BodySubscribers.ofPublisher(); - Publisher> pub = S.newErroredPublisher(); - pub.subscribe(sub); - return sub.getBody().toCompletableFuture().join(); - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java deleted file mode 100644 index 0d2410ac333..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfString - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfString() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofString(StandardCharsets.UTF_8); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java deleted file mode 100644 index cb901f02674..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersReplacing - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersReplacing() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - /* it doesn't matter what we are replacing with */ - return BodySubscribers.replacing(Boolean.TRUE); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java deleted file mode 100644 index c3f86b753d9..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; -import java.util.stream.Stream; - -/* - * S for Support. - * - * Auxiliary methods for tests that check conformance with reactive streams - * specification. - * - * Short name is for the sake of convenience calling this class' static methods. - * It could've been called Support or TckSupport, but then we would need to - * place this class in its own package so as to use "import static". - */ -public class S { - - private static final Random RANDOM = new SecureRandom(); - - private S() { } - - public static List listOfBuffersFromBufferOfNBytes(int nBytes) { - return scatterBuffer(bufferOfNRandomBytes(nBytes)); - } - - /* - * Spreads the remaining contents of the given byte buffer across a number - * of buffers put into a list. - */ - public static List scatterBuffer(ByteBuffer src) { - List buffers = new ArrayList<>(); - while (src.hasRemaining()) { - // We do not allow empty buffers ~~~~~~~~~~~~~~~~v - int capacity = RANDOM.nextInt(src.remaining()) + 1; - ByteBuffer b = ByteBuffer.allocate(capacity); - for (int i = 0; i < capacity; i++) { - b.put(src.get()); - } - b.flip(); - buffers.add(b); - } - return List.copyOf(buffers); - } - - public static ByteBuffer bufferOfNRandomBytes(int capacity) { - return ByteBuffer.wrap(arrayOfNRandomBytes(capacity)); - } - - public static byte[] arrayOfNRandomBytes(int nBytes) { - byte[] contents = new byte[nBytes]; - RANDOM.nextBytes(contents); - return contents; - } - - public static InputStream inputStreamOfNReads(long n) { - return new NReadsInputStream(n); - } - - /* - * Convenience method for testing publishers. - */ - public static byte[] arrayOfNRandomBytes(long nBytes) { - return arrayOfNRandomBytes((int) nBytes); - } - - public static ByteBuffer bufferOfNRandomASCIIBytes(int capacity) { - String alphaNumeric = "abcdefghijklmnopqrstuvwxyz1234567890"; - StringBuilder builder = new StringBuilder(capacity); - for (int i = 0; i < capacity; i++) { - int idx = RANDOM.nextInt(alphaNumeric.length()); - builder.append(alphaNumeric.charAt(idx)); - } - return ByteBuffer.wrap(builder.toString().getBytes( - StandardCharsets.US_ASCII)); - } - - /* - * Returns a simple non-compliant Subscriber. - * - * This Subscriber is useful for testing our adaptors and wrappers, to make - * sure they do not delegate RS compliance to the underlying (and foreign to - * java.net.http codebase) Subscribers, but rather comply themselves. - * - * Here's an example: - * - * public void onSubscribe(Subscription s) { - * delegate.onSubscribe(s); - * } - * - * The snippet above cannot be considered a good implementation of a - * Subscriber if `delegate` is an unknown Subscriber. In this case the - * implementation should independently check all the rules from the RS spec - * related to subscribers. - */ - public static Subscriber nonCompliantSubscriber() { - return new Subscriber<>() { - - @Override - public void onSubscribe(Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { } - - @Override - public void onError(Throwable throwable) { } - - @Override - public void onComplete() { } - }; - } - - public static int randomIntUpTo(int bound) { - return RANDOM.nextInt(bound); - } - - /* - * Signals an error to its subscribers immediately after subscription. - */ - public static Publisher newErroredPublisher() { - return subscriber -> { - subscriber.onSubscribe(new Subscription() { - @Override - public void request(long n) { } - - @Override - public void cancel() { } - }); - subscriber.onError(new IOException()); - }; - } - - /* - * Publishes the elements obtained from the stream and signals completion. - * Can be cancelled, but cannot signal an error. - * - * This trivial ad-hoc implementation of Publisher was created so as to - * publish lists of byte buffers. We can publish ByteBuffer, but we can't - * seem to publish List since there's no readily available - * publisher of those, nor there's a simple adaptor. - */ - public static Publisher publisherOfStream(Stream stream) - { - if (stream == null) { - throw new NullPointerException(); - } - return new Publisher() { - @Override - public void subscribe(Subscriber subscriber) { - if (subscriber == null) { - throw new NullPointerException(); - } - Subscription subscription = new Subscription() { - - boolean inOnNext; // recursion control - volatile boolean cancelled; - long demand; - final Iterator supply = stream.iterator(); - - @Override - public void request(long n) { - demand = demand + n < 0 ? Long.MAX_VALUE : demand + n; - if (inOnNext) { - return; - } - if (cancelled) - return; - if (n <= 0) { - cancelled = true; - subscriber.onError(new IllegalArgumentException( - "non-positive subscription request")); - return; - } - while (supply.hasNext() && demand > 0 && !cancelled) { - demand--; - inOnNext = true; - try { - T item = supply.next(); - subscriber.onNext(item); - } finally { - inOnNext = false; - } - } - if (!supply.hasNext()) { - cancelled = true; - subscriber.onComplete(); - } - } - - @Override - public void cancel() { - cancelled = true; - } - }; - subscriber.onSubscribe(subscription); - } - }; - } - - static final class NReadsInputStream extends InputStream { - - private static final int EOF = -1; - private long readsLeft; - - NReadsInputStream(long n) { - if (n < 0) { - throw new IllegalArgumentException(String.valueOf(n)); - } - this.readsLeft = n; - } - - @Override - public int read() { - if (readsLeft == 0L) { - return EOF; - } - readsLeft--; - return S.randomIntUpTo(256); - } - - @Override - public int read(byte[] b, int off, int len) { - Objects.checkFromIndexSize(off, len, b.length); - // Must return 0 if len == 0, - // even if there are no more reads left - if (len == 0) { - return 0; - } - if (readsLeft == 0L) { - return EOF; - } - readsLeft--; - // At least one byte MUST be read, but we can read - // less than `len` bytes - int r = RANDOM.nextInt(len) + 1; - for (int i = 0; i < r; i++) { - b[i] = (byte) randomIntUpTo(256); - } - return r; - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java deleted file mode 100644 index a762b4edf1e..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -public class STest { - - @DataProvider(name = "bufferSizes") - public static Object[][] bufferSizes() { - return new Object[][]{ - { 1}, - { 2}, - { 3}, - { 4}, - {16}, - {17}, - }; - } - - @DataProvider - public static Object[][] inputStream() { - return new Object[][] { - { 0, 1}, - { 1, 2}, - { 1, 3}, - { 1, 4}, - { 2, 1}, - { 2, 2}, - { 2, 3}, - { 2, 4}, - { 2, 13}, - { 3, 1}, - { 3, 2}, - { 3, 3}, - { 3, 4}, - { 3, 17}, - { 4, 1}, - { 4, 2}, - { 4, 3}, - { 4, 4}, - { 4, 5}, - { 13, 1}, - { 13, 2}, - { 13, 13}, - { 16, 18}, - { 17, 2}, - {255, 1}, - {256, 255}, - {257, 267}, - }; - } - - @Test - public void testScatter0() { - List buffers = S.scatterBuffer( - ByteBuffer.allocate(0)); - assertEquals(buffers.size(), 0); - } - - @Test(dataProvider = "bufferSizes") - public void testScatterN(int n) { - final ByteBuffer src = S.bufferOfNRandomBytes(n); - final int srcLength = src.remaining(); - ByteBuffer copy = ByteBuffer.wrap(Arrays.copyOf(src.array(), - src.array().length)); - List buffers = S.scatterBuffer(src); - int m = 0; - for (ByteBuffer b : buffers) { - m += b.remaining(); - while (b.hasRemaining() & copy.hasRemaining()) { - assertEquals(b.get(), copy.get()); - } - } - assertEquals(m, srcLength); - } - - @Test(dataProvider = "inputStream") - public void testInputStreamOfNReads(int n, int capacity) throws IOException { - InputStream s = S.inputStreamOfNReads(n); - int count = 0; - byte[] b = new byte[capacity]; - while (s.read(b) != -1) { - count++; - } - assertEquals(count, n); - assertTrue(s.read() == -1); - assertTrue(s.read(b) == -1); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java deleted file mode 100644 index c7e08eff523..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8226602 - * @summary Tests convenience reactive primitives with RS TCK - * - * @library ../reactivestreams-tck - * @build S - * - * @compile -encoding UTF-8 SPublisherOfStream.java - * - * @compile -encoding UTF-8 BodyPublishersFromPublisher.java - * @compile -encoding UTF-8 BodyPublishersNoBody.java - * @compile -encoding UTF-8 BodyPublishersOfByteArray.java - * @compile -encoding UTF-8 BodyPublishersOfByteArrays.java - * @compile -encoding UTF-8 BodyPublishersOfFile.java - * @compile -encoding UTF-8 BodyPublishersOfInputStream.java - * @compile -encoding UTF-8 BodyPublishersOfSubByteArray.java - * @compile -encoding UTF-8 BodyPublishersConcat.java - * - * @compile -encoding UTF-8 BodySubscribersBuffering.java - * @compile -encoding UTF-8 BodySubscribersDiscarding.java - * @compile -encoding UTF-8 BodySubscribersFromLineSubscriber.java - * @compile -encoding UTF-8 BodySubscribersFromSubscriber.java - * @compile -encoding UTF-8 BodySubscribersMapping.java - * @compile -encoding UTF-8 BodySubscribersOfByteArray.java - * @compile -encoding UTF-8 BodySubscribersOfByteArrayConsumer.java - * @compile -encoding UTF-8 BodySubscribersOfFile.java - * @compile -encoding UTF-8 BodySubscribersOfInputStream.java - * @compile -encoding UTF-8 BodySubscribersOfLines.java - * @compile -encoding UTF-8 BodySubscribersOfPublisher.java - * @compile -encoding UTF-8 BodySubscribersOfPublisher1.java - * @compile -encoding UTF-8 BodySubscribersOfPublisherPublisher.java - * @compile -encoding UTF-8 BodySubscribersOfString.java - * @compile -encoding UTF-8 BodySubscribersReplacing.java - * - * @run testng/othervm STest - * @run testng/othervm SPublisherOfStream - * - * @run testng/othervm BodyPublishersFromPublisher - * @run testng/othervm BodyPublishersNoBody - * @run testng/othervm BodyPublishersOfByteArray - * @run testng/othervm BodyPublishersOfByteArrays - * @run testng/othervm BodyPublishersOfFile - * @run testng/othervm BodyPublishersOfInputStream - * @run testng/othervm BodyPublishersOfSubByteArray - * @run testng/othervm BodyPublishersConcat - * - * @run testng/othervm BodySubscribersBuffering - * @run testng/othervm BodySubscribersDiscarding - * @run testng/othervm BodySubscribersFromLineSubscriber - * @run testng/othervm BodySubscribersFromSubscriber - * @run testng/othervm BodySubscribersMapping - * @run testng/othervm BodySubscribersOfByteArray - * @run testng/othervm BodySubscribersOfByteArrayConsumer - * @run testng/othervm BodySubscribersOfFile - * @run testng/othervm BodySubscribersOfInputStream - * @run testng/othervm BodySubscribersOfLines - * @run testng/othervm BodySubscribersOfPublisher - * @run testng/othervm BodySubscribersOfPublisher1 - * @run testng/othervm BodySubscribersOfPublisherPublisher - * @run testng/othervm BodySubscribersOfString - * @run testng/othervm BodySubscribersReplacing - * - * @key randomness - */ -public class TckDriver { - /* - #### General Information - - 1. This JTREG test aggregates multiple TestNG tests. This is because - these tests share a common library (reactivestreams-tck), and we don't - want this library to be compiled separately for each of those tests. - - 2. Tests that use RS TCK are compiled with the UTF-8 encoding. This is - performed for the sake of reactivestreams-tck. We don't want to patch - the TCK because of the extra merging work in the future, should we bring - update(s) from the RS repo. - - #### Tests - - 1. The purpose of each test should be easily digestible. The name of the - test is derived from the very entity the test exercises. For example, - - the BodyPublishersOfFile test exercises the BodyPublisher obtained - by calling BodyPublishers.ofFile(Path) - - the BodySubscribersOfFile test exercises the BodySubscriber obtained - by calling BodySubscribers.ofFile(Path) - - 2. RS TCK requires PublisherVerification tests to produce publishers - capable of emitting a certain number of elements. In order to achieve - this, we use some knowledge of the internal workings of our publishers. - An example would be a chunk size a publisher uses to deliver a portion - of data. Without knowing that it is not possible to guarantee that the - publisher will emit a particular number of elements. - - 3. Typically our publishers cannot be created in a known failed state. - In this case the corresponding `createFailedFlowPublisher` method - returns `null`. - - 4. SubscriberBlackBoxVerification uses the `createElement(int element)` - method. Our implementations usually cap the amount of data created by - this method, because it's not known beforehand how big the `element` - value is. Hence, sometimes there's code like as follows: - - @Override - public List createElement(int element) { - return scatterBuffer( - bufferOfNRandomASCIIBytes(element % 17)); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ - } - - 5. The amount of testing RS TCK performs on a publisher seems to depend - on the number of elements this publisher reports it can emit. Sometimes - a code like the following can be seen in the tests: - - @Override public long maxElementsFromPublisher() { - return 21; - ~~~~~~~~~~~^ - } - - This magic number is a result of trial and error and seems to unlock - most of the tests. Reporting big values (e.g. Long.MAX_VALUE - 1) is - not an option for most of our publishers because they require to have - all the elements upfront. - - 6. It doesn't seem currently feasible to provide SubscriberWhiteboxVerification - tests as a) it's not clear how much better the coverage is and b) it's - significantly harder to code that. - - #### S (Support) - - Support utilities are being tested (STest) too. - */ -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java deleted file mode 100644 index 8452dcd5539..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams; - -import java.util.concurrent.Flow; -import static java.util.Objects.requireNonNull; - -/** - * Bridge between Reactive Streams API and the Java 9 {@link java.util.concurrent.Flow} API. - */ -public final class FlowAdapters { - /** Utility class. */ - private FlowAdapters() { - throw new IllegalStateException("No instances!"); - } - - /** - * Converts a Flow Publisher into a Reactive Streams Publisher. - * @param the element type - * @param flowPublisher the source Flow Publisher to convert - * @return the equivalent Reactive Streams Publisher - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Publisher toPublisher( - Flow.Publisher flowPublisher) { - requireNonNull(flowPublisher, "flowPublisher"); - final org.reactivestreams.Publisher publisher; - if (flowPublisher instanceof FlowPublisherFromReactive) { - publisher = (org.reactivestreams.Publisher)(((FlowPublisherFromReactive)flowPublisher).reactiveStreams); - } else if (flowPublisher instanceof org.reactivestreams.Publisher) { - publisher = (org.reactivestreams.Publisher)flowPublisher; - } else { - publisher = new ReactivePublisherFromFlow(flowPublisher); - } - return publisher; - } - - /** - * Converts a Reactive Streams Publisher into a Flow Publisher. - * @param the element type - * @param reactiveStreamsPublisher the source Reactive Streams Publisher to convert - * @return the equivalent Flow Publisher - */ - @SuppressWarnings("unchecked") - public static Flow.Publisher toFlowPublisher( - org.reactivestreams.Publisher reactiveStreamsPublisher - ) { - requireNonNull(reactiveStreamsPublisher, "reactiveStreamsPublisher"); - final Flow.Publisher flowPublisher; - if (reactiveStreamsPublisher instanceof ReactivePublisherFromFlow) { - flowPublisher = (Flow.Publisher)(((ReactivePublisherFromFlow)reactiveStreamsPublisher).flow); - } else if (reactiveStreamsPublisher instanceof Flow.Publisher) { - flowPublisher = (Flow.Publisher)reactiveStreamsPublisher; - } else { - flowPublisher = new FlowPublisherFromReactive(reactiveStreamsPublisher); - } - return flowPublisher; - } - - /** - * Converts a Flow Processor into a Reactive Streams Processor. - * @param the input value type - * @param the output value type - * @param flowProcessor the source Flow Processor to convert - * @return the equivalent Reactive Streams Processor - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Processor toProcessor( - Flow.Processor flowProcessor - ) { - requireNonNull(flowProcessor, "flowProcessor"); - final org.reactivestreams.Processor processor; - if (flowProcessor instanceof FlowToReactiveProcessor) { - processor = (org.reactivestreams.Processor)(((FlowToReactiveProcessor)flowProcessor).reactiveStreams); - } else if (flowProcessor instanceof org.reactivestreams.Processor) { - processor = (org.reactivestreams.Processor)flowProcessor; - } else { - processor = new ReactiveToFlowProcessor(flowProcessor); - } - return processor; - } - - /** - * Converts a Reactive Streams Processor into a Flow Processor. - * @param the input value type - * @param the output value type - * @param reactiveStreamsProcessor the source Reactive Streams Processor to convert - * @return the equivalent Flow Processor - */ - @SuppressWarnings("unchecked") - public static Flow.Processor toFlowProcessor( - org.reactivestreams.Processor reactiveStreamsProcessor - ) { - requireNonNull(reactiveStreamsProcessor, "reactiveStreamsProcessor"); - final Flow.Processor flowProcessor; - if (reactiveStreamsProcessor instanceof ReactiveToFlowProcessor) { - flowProcessor = (Flow.Processor)(((ReactiveToFlowProcessor)reactiveStreamsProcessor).flow); - } else if (reactiveStreamsProcessor instanceof Flow.Processor) { - flowProcessor = (Flow.Processor)reactiveStreamsProcessor; - } else { - flowProcessor = new FlowToReactiveProcessor(reactiveStreamsProcessor); - } - return flowProcessor; - } - - /** - * Converts a Reactive Streams Subscriber into a Flow Subscriber. - * @param the input and output value type - * @param reactiveStreamsSubscriber the Reactive Streams Subscriber instance to convert - * @return the equivalent Flow Subscriber - */ - @SuppressWarnings("unchecked") - public static Flow.Subscriber toFlowSubscriber(org.reactivestreams.Subscriber reactiveStreamsSubscriber) { - requireNonNull(reactiveStreamsSubscriber, "reactiveStreamsSubscriber"); - final Flow.Subscriber flowSubscriber; - if (reactiveStreamsSubscriber instanceof ReactiveToFlowSubscriber) { - flowSubscriber = (Flow.Subscriber)((ReactiveToFlowSubscriber)reactiveStreamsSubscriber).flow; - } else if (reactiveStreamsSubscriber instanceof Flow.Subscriber) { - flowSubscriber = (Flow.Subscriber)reactiveStreamsSubscriber; - } else { - flowSubscriber = new FlowToReactiveSubscriber(reactiveStreamsSubscriber); - } - return flowSubscriber; - } - - /** - * Converts a Flow Subscriber into a Reactive Streams Subscriber. - * @param the input and output value type - * @param flowSubscriber the Flow Subscriber instance to convert - * @return the equivalent Reactive Streams Subscriber - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Subscriber toSubscriber(Flow.Subscriber flowSubscriber) { - requireNonNull(flowSubscriber, "flowSubscriber"); - final org.reactivestreams.Subscriber subscriber; - if (flowSubscriber instanceof FlowToReactiveSubscriber) { - subscriber = (org.reactivestreams.Subscriber)((FlowToReactiveSubscriber)flowSubscriber).reactiveStreams; - } else if (flowSubscriber instanceof org.reactivestreams.Subscriber) { - subscriber = (org.reactivestreams.Subscriber)flowSubscriber; - } else { - subscriber = new ReactiveToFlowSubscriber(flowSubscriber); - } - return subscriber; - } - - /** - * Wraps a Reactive Streams Subscription and converts the calls to a Flow Subscription. - */ - static final class FlowToReactiveSubscription implements Flow.Subscription { - final org.reactivestreams.Subscription reactiveStreams; - - public FlowToReactiveSubscription(org.reactivestreams.Subscription reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void request(long n) { - reactiveStreams.request(n); - } - - @Override - public void cancel() { - reactiveStreams.cancel(); - } - - } - - /** - * Wraps a Flow Subscription and converts the calls to a Reactive Streams Subscription. - */ - static final class ReactiveToFlowSubscription implements org.reactivestreams.Subscription { - final Flow.Subscription flow; - - public ReactiveToFlowSubscription(Flow.Subscription flow) { - this.flow = flow; - } - - @Override - public void request(long n) { - flow.request(n); - } - - @Override - public void cancel() { - flow.cancel(); - } - - - } - - /** - * Wraps a Reactive Streams Subscriber and forwards methods of the Flow Subscriber to it. - * @param the element type - */ - static final class FlowToReactiveSubscriber implements Flow.Subscriber { - final org.reactivestreams.Subscriber reactiveStreams; - - public FlowToReactiveSubscriber(org.reactivestreams.Subscriber reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription)); - } - - @Override - public void onNext(T item) { - reactiveStreams.onNext(item); - } - - @Override - public void onError(Throwable throwable) { - reactiveStreams.onError(throwable); - } - - @Override - public void onComplete() { - reactiveStreams.onComplete(); - } - - } - - /** - * Wraps a Flow Subscriber and forwards methods of the Reactive Streams Subscriber to it. - * @param the element type - */ - static final class ReactiveToFlowSubscriber implements org.reactivestreams.Subscriber { - final Flow.Subscriber flow; - - public ReactiveToFlowSubscriber(Flow.Subscriber flow) { - this.flow = flow; - } - - @Override - public void onSubscribe(org.reactivestreams.Subscription subscription) { - flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription)); - } - - @Override - public void onNext(T item) { - flow.onNext(item); - } - - @Override - public void onError(Throwable throwable) { - flow.onError(throwable); - } - - @Override - public void onComplete() { - flow.onComplete(); - } - - } - - /** - * Wraps a Flow Processor and forwards methods of the Reactive Streams Processor to it. - * @param the input type - * @param the output type - */ - static final class ReactiveToFlowProcessor implements org.reactivestreams.Processor { - final Flow.Processor flow; - - public ReactiveToFlowProcessor(Flow.Processor flow) { - this.flow = flow; - } - - @Override - public void onSubscribe(org.reactivestreams.Subscription subscription) { - flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription)); - } - - @Override - public void onNext(T t) { - flow.onNext(t); - } - - @Override - public void onError(Throwable t) { - flow.onError(t); - } - - @Override - public void onComplete() { - flow.onComplete(); - } - - @Override - public void subscribe(org.reactivestreams.Subscriber s) { - flow.subscribe((s == null) ? null : new FlowToReactiveSubscriber(s)); - } - } - - /** - * Wraps a Reactive Streams Processor and forwards methods of the Flow Processor to it. - * @param the input type - * @param the output type - */ - static final class FlowToReactiveProcessor implements Flow.Processor { - final org.reactivestreams.Processor reactiveStreams; - - public FlowToReactiveProcessor(org.reactivestreams.Processor reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription)); - } - - @Override - public void onNext(T t) { - reactiveStreams.onNext(t); - } - - @Override - public void onError(Throwable t) { - reactiveStreams.onError(t); - } - - @Override - public void onComplete() { - reactiveStreams.onComplete(); - } - - @Override - public void subscribe(Flow.Subscriber s) { - reactiveStreams.subscribe((s == null) ? null : new ReactiveToFlowSubscriber(s)); - } - } - - /** - * Reactive Streams Publisher that wraps a Flow Publisher. - * @param the element type - */ - static final class ReactivePublisherFromFlow implements org.reactivestreams.Publisher { - final Flow.Publisher flow; - - public ReactivePublisherFromFlow(Flow.Publisher flowPublisher) { - this.flow = flowPublisher; - } - - @Override - public void subscribe(org.reactivestreams.Subscriber reactive) { - flow.subscribe((reactive == null) ? null : new FlowToReactiveSubscriber(reactive)); - } - } - - /** - * Flow Publisher that wraps a Reactive Streams Publisher. - * @param the element type - */ - static final class FlowPublisherFromReactive implements Flow.Publisher { - - final org.reactivestreams.Publisher reactiveStreams; - - public FlowPublisherFromReactive(org.reactivestreams.Publisher reactivePublisher) { - this.reactiveStreams = reactivePublisher; - } - - @Override - public void subscribe(Flow.Subscriber flow) { - reactiveStreams.subscribe((flow == null) ? null : new ReactiveToFlowSubscriber(flow)); - } - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java deleted file mode 100644 index ea6eb2908e0..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams; - -/** - * A {@link Publisher} is a provider of a potentially unbounded number of sequenced elements, publishing them according to - * the demand received from its {@link Subscriber}(s). - *

    - * A {@link Publisher} can serve multiple {@link Subscriber}s subscribed {@link #subscribe(Subscriber)} dynamically - * at various points in time. - * - * @param the type of element signaled. - */ -public interface Publisher { - - /** - * Request {@link Publisher} to start streaming data. - *

    - * This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}. - *

    - * Each {@link Subscription} will work for only a single {@link Subscriber}. - *

    - * A {@link Subscriber} should only subscribe once to a single {@link Publisher}. - *

    - * If the {@link Publisher} rejects the subscription attempt or otherwise fails it will - * signal the error via {@link Subscriber#onError}. - * - * @param s the {@link Subscriber} that will consume signals from this {@link Publisher} - */ - public void subscribe(Subscriber s); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java deleted file mode 100644 index 5ce405aa430..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams; - -/** - * Will receive call to {@link #onSubscribe(Subscription)} once after passing an instance of {@link Subscriber} to {@link Publisher#subscribe(Subscriber)}. - *

    - * No further notifications will be received until {@link Subscription#request(long)} is called. - *

    - * After signaling demand: - *

      - *
    • One or more invocations of {@link #onNext(Object)} up to the maximum number defined by {@link Subscription#request(long)}
    • - *
    • Single invocation of {@link #onError(Throwable)} or {@link Subscriber#onComplete()} which signals a terminal state after which no further events will be sent. - *
    - *

    - * Demand can be signaled via {@link Subscription#request(long)} whenever the {@link Subscriber} instance is capable of handling more. - * - * @param the type of element signaled. - */ -public interface Subscriber { - /** - * Invoked after calling {@link Publisher#subscribe(Subscriber)}. - *

    - * No data will start flowing until {@link Subscription#request(long)} is invoked. - *

    - * It is the responsibility of this {@link Subscriber} instance to call {@link Subscription#request(long)} whenever more data is wanted. - *

    - * The {@link Publisher} will send notifications only in response to {@link Subscription#request(long)}. - * - * @param s - * {@link Subscription} that allows requesting data via {@link Subscription#request(long)} - */ - public void onSubscribe(Subscription s); - - /** - * Data notification sent by the {@link Publisher} in response to requests to {@link Subscription#request(long)}. - * - * @param t the element signaled - */ - public void onNext(T t); - - /** - * Failed terminal state. - *

    - * No further events will be sent even if {@link Subscription#request(long)} is invoked again. - * - * @param t the throwable signaled - */ - public void onError(Throwable t); - - /** - * Successful terminal state. - *

    - * No further events will be sent even if {@link Subscription#request(long)} is invoked again. - */ - public void onComplete(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java deleted file mode 100644 index 244ac672e05..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams; - -/** - * A {@link Subscription} represents a one-to-one lifecycle of a {@link Subscriber} subscribing to a {@link Publisher}. - *

    - * It can only be used once by a single {@link Subscriber}. - *

    - * It is used to both signal desire for data and cancel demand (and allow resource cleanup). - * - */ -public interface Subscription { - /** - * No events will be sent by a {@link Publisher} until demand is signaled via this method. - *

    - * It can be called however often and whenever needed—but if the outstanding cumulative demand ever becomes Long.MAX_VALUE or more, - * it may be treated by the {@link Publisher} as "effectively unbounded". - *

    - * Whatever has been requested can be sent by the {@link Publisher} so only signal demand for what can be safely handled. - *

    - * A {@link Publisher} can send less than is requested if the stream ends but - * then must emit either {@link Subscriber#onError(Throwable)} or {@link Subscriber#onComplete()}. - * - * @param n the strictly positive number of elements to requests to the upstream {@link Publisher} - */ - public void request(long n); - - /** - * Request the {@link Publisher} to stop sending data and clean up resources. - *

    - * Data may still be sent to meet previously signalled demand after calling cancel. - */ - public void cancel(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java deleted file mode 100644 index ed09f07bd84..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.example.unicast; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.Iterator; -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * AsyncIterablePublisher is an implementation of Reactive Streams `Publisher` - * which executes asynchronously, using a provided `Executor` and produces elements - * from a given `Iterable` in a "unicast" configuration to its `Subscribers`. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public class AsyncIterablePublisher implements Publisher { - private final static int DEFAULT_BATCHSIZE = 1024; - - private final Iterable elements; // This is our data source / generator - private final Executor executor; // This is our thread pool, which will make sure that our Publisher runs asynchronously to its Subscribers - private final int batchSize; // In general, if one uses an `Executor`, one should be nice nad not hog a thread for too long, this is the cap for that, in elements - - public AsyncIterablePublisher(final Iterable elements, final Executor executor) { - this(elements, DEFAULT_BATCHSIZE, executor); - } - - public AsyncIterablePublisher(final Iterable elements, final int batchSize, final Executor executor) { - if (elements == null) throw null; - if (executor == null) throw null; - if (batchSize < 1) throw new IllegalArgumentException("batchSize must be greater than zero!"); - this.elements = elements; - this.executor = executor; - this.batchSize = batchSize; - } - - @Override - public void subscribe(final Subscriber s) { - // As per rule 1.11, we have decided to support multiple subscribers in a unicast configuration - // for this `Publisher` implementation. - // As per 2.13, this method must return normally (i.e. not throw) - new SubscriptionImpl(s).init(); - } - - // These represent the protocol of the `AsyncIterablePublishers` SubscriptionImpls - static interface Signal {}; - enum Cancel implements Signal { Instance; }; - enum Subscribe implements Signal { Instance; }; - enum Send implements Signal { Instance; }; - static final class Request implements Signal { - final long n; - Request(final long n) { - this.n = n; - } - }; - - // This is our implementation of the Reactive Streams `Subscription`, - // which represents the association between a `Publisher` and a `Subscriber`. - final class SubscriptionImpl implements Subscription, Runnable { - final Subscriber subscriber; // We need a reference to the `Subscriber` so we can talk to it - private boolean cancelled = false; // This flag will track whether this `Subscription` is to be considered cancelled or not - private long demand = 0; // Here we track the current demand, i.e. what has been requested but not yet delivered - private Iterator iterator; // This is our cursor into the data stream, which we will send to the `Subscriber` - - SubscriptionImpl(final Subscriber subscriber) { - // As per rule 1.09, we need to throw a `java.lang.NullPointerException` if the `Subscriber` is `null` - if (subscriber == null) throw null; - this.subscriber = subscriber; - } - - // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscription`, like `request` and `cancel` - private final ConcurrentLinkedQueue inboundSignals = new ConcurrentLinkedQueue(); - - // We are using this `AtomicBoolean` to make sure that this `Subscription` doesn't run concurrently with itself, - // which would violate rule 1.3 among others (no concurrent notifications). - private final AtomicBoolean on = new AtomicBoolean(false); - - // This method will register inbound demand from our `Subscriber` and validate it against rule 3.9 and rule 3.17 - private void doRequest(final long n) { - if (n < 1) - terminateDueTo(new IllegalArgumentException(subscriber + " violated the Reactive Streams rule 3.9 by requesting a non-positive number of elements.")); - else if (demand + n < 1) { - // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE` we treat the signalled demand as "effectively unbounded" - demand = Long.MAX_VALUE; // Here we protect from the overflow and treat it as "effectively unbounded" - doSend(); // Then we proceed with sending data downstream - } else { - demand += n; // Here we record the downstream demand - doSend(); // Then we can proceed with sending data downstream - } - } - - // This handles cancellation requests, and is idempotent, thread-safe and not synchronously performing heavy computations as specified in rule 3.5 - private void doCancel() { - cancelled = true; - } - - // Instead of executing `subscriber.onSubscribe` synchronously from within `Publisher.subscribe` - // we execute it asynchronously, this is to avoid executing the user code (`Iterable.iterator`) on the calling thread. - // It also makes it easier to follow rule 1.9 - private void doSubscribe() { - try { - iterator = elements.iterator(); - if (iterator == null) - iterator = Collections.emptyList().iterator(); // So we can assume that `iterator` is never null - } catch(final Throwable t) { - subscriber.onSubscribe(new Subscription() { // We need to make sure we signal onSubscribe before onError, obeying rule 1.9 - @Override public void cancel() {} - @Override public void request(long n) {} - }); - terminateDueTo(t); // Here we send onError, obeying rule 1.09 - } - - if (!cancelled) { - // Deal with setting up the subscription with the subscriber - try { - subscriber.onSubscribe(this); - } catch(final Throwable t) { // Due diligence to obey 2.13 - terminateDueTo(new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onSubscribe.", t)); - } - - // Deal with already complete iterators promptly - boolean hasElements = false; - try { - hasElements = iterator.hasNext(); - } catch(final Throwable t) { - terminateDueTo(t); // If hasNext throws, there's something wrong and we need to signal onError as per 1.2, 1.4, - } - - // If we don't have anything to deliver, we're already done, so lets do the right thing and - // not wait for demand to deliver `onComplete` as per rule 1.2 and 1.3 - if (!hasElements) { - try { - doCancel(); // Rule 1.6 says we need to consider the `Subscription` cancelled when `onComplete` is signalled - subscriber.onComplete(); - } catch(final Throwable t) { // As per rule 2.13, `onComplete` is not allowed to throw exceptions, so we do what we can, and log this. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onComplete.", t)).printStackTrace(System.err); - } - } - } - } - - // This is our behavior for producing elements downstream - private void doSend() { - try { - // In order to play nice with the `Executor` we will only send at-most `batchSize` before - // rescheduing ourselves and relinquishing the current thread. - int leftInBatch = batchSize; - do { - T next; - boolean hasNext; - try { - next = iterator.next(); // We have already checked `hasNext` when subscribing, so we can fall back to testing -after- `next` is called. - hasNext = iterator.hasNext(); // Need to keep track of End-of-Stream - } catch (final Throwable t) { - terminateDueTo(t); // If `next` or `hasNext` throws (they can, since it is user-provided), we need to treat the stream as errored as per rule 1.4 - return; - } - subscriber.onNext(next); // Then we signal the next element downstream to the `Subscriber` - if (!hasNext) { // If we are at End-of-Stream - doCancel(); // We need to consider this `Subscription` as cancelled as per rule 1.6 - subscriber.onComplete(); // Then we signal `onComplete` as per rule 1.2 and 1.5 - } - } while (!cancelled // This makes sure that rule 1.8 is upheld, i.e. we need to stop signalling "eventually" - && --leftInBatch > 0 // This makes sure that we only send `batchSize` number of elements in one go (so we can yield to other Runnables) - && --demand > 0); // This makes sure that rule 1.1 is upheld (sending more than was demanded) - - if (!cancelled && demand > 0) // If the `Subscription` is still alive and well, and we have demand to satisfy, we signal ourselves to send more data - signal(Send.Instance); - } catch(final Throwable t) { - // We can only get here if `onNext` or `onComplete` threw, and they are not allowed to according to 2.13, so we can only cancel and log here. - doCancel(); // Make sure that we are cancelled, since we cannot do anything else since the `Subscriber` is faulty. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onNext or onComplete.", t)).printStackTrace(System.err); - } - } - - // This is a helper method to ensure that we always `cancel` when we signal `onError` as per rule 1.6 - private void terminateDueTo(final Throwable t) { - cancelled = true; // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6 - try { - subscriber.onError(t); // Then we signal the error downstream, to the `Subscriber` - } catch(final Throwable t2) { // If `onError` throws an exception, this is a spec violation according to rule 1.9, and all we can do is to log it. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - - // What `signal` does is that it sends signals to the `Subscription` asynchronously - private void signal(final Signal signal) { - if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us - tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already - } - - // This is the main "event loop" if you so will - @Override public final void run() { - if(on.get()) { // establishes a happens-before relationship with the end of the previous run - try { - final Signal s = inboundSignals.poll(); // We take a signal off the queue - if (!cancelled) { // to make sure that we follow rule 1.8, 3.6 and 3.7 - - // Below we simply unpack the `Signal`s and invoke the corresponding methods - if (s instanceof Request) - doRequest(((Request)s).n); - else if (s == Send.Instance) - doSend(); - else if (s == Cancel.Instance) - doCancel(); - else if (s == Subscribe.Instance) - doSubscribe(); - } - } finally { - on.set(false); // establishes a happens-before relationship with the beginning of the next run - if(!inboundSignals.isEmpty()) // If we still have signals to process - tryScheduleToExecute(); // Then we try to schedule ourselves to execute again - } - } - } - - // This method makes sure that this `Subscription` is only running on one Thread at a time, - // this is important to make sure that we follow rule 1.3 - private final void tryScheduleToExecute() { - if(on.compareAndSet(false, true)) { - try { - executor.execute(this); - } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully - if (!cancelled) { - doCancel(); // First of all, this failure is not recoverable, so we need to follow rule 1.4 and 1.6 - try { - terminateDueTo(new IllegalStateException("Publisher terminated due to unavailable Executor.", t)); - } finally { - inboundSignals.clear(); // We're not going to need these anymore - // This subscription is cancelled by now, but letting it become schedulable again means - // that we can drain the inboundSignals queue if anything arrives after clearing - on.set(false); - } - } - } - } - } - - // Our implementation of `Subscription.request` sends a signal to the Subscription that more elements are in demand - @Override public void request(final long n) { - signal(new Request(n)); - } - // Our implementation of `Subscription.cancel` sends a signal to the Subscription that the `Subscriber` is not interested in any more elements - @Override public void cancel() { - signal(Cancel.Instance); - } - // The reason for the `init` method is that we want to ensure the `SubscriptionImpl` - // is completely constructed before it is exposed to the thread pool, therefor this - // method is only intended to be invoked once, and immediately after the constructor has - // finished. - void init() { - signal(Subscribe.Instance); - } - }; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java deleted file mode 100644 index a610a93cca4..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.example.unicast; - -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * AsyncSubscriber is an implementation of Reactive Streams `Subscriber`, - * it runs asynchronously (on an Executor), requests one element - * at a time, and invokes a user-defined method to process each element. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public abstract class AsyncSubscriber implements Subscriber, Runnable { - - // Signal represents the asynchronous protocol between the Publisher and Subscriber - private static interface Signal {} - - private enum OnComplete implements Signal { Instance; } - - private static class OnError implements Signal { - public final Throwable error; - public OnError(final Throwable error) { this.error = error; } - } - - private static class OnNext implements Signal { - public final T next; - public OnNext(final T next) { this.next = next; } - } - - private static class OnSubscribe implements Signal { - public final Subscription subscription; - public OnSubscribe(final Subscription subscription) { this.subscription = subscription; } - } - - private Subscription subscription; // Obeying rule 3.1, we make this private! - private boolean done; // It's useful to keep track of whether this Subscriber is done or not - private final Executor executor; // This is the Executor we'll use to be asynchronous, obeying rule 2.2 - - // Only one constructor, and it's only accessible for the subclasses - protected AsyncSubscriber(Executor executor) { - if (executor == null) throw null; - this.executor = executor; - } - - // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements - // herefor we also need to cancel our `Subscription`. - private final void done() { - //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to. - done = true; // If `whenNext` throws an exception, let's consider ourselves done (not accepting more elements) - if (subscription != null) { // If we are bailing out before we got a `Subscription` there's little need for cancelling it. - try { - subscription.cancel(); // Cancel the subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } - } - - // This method is invoked when the OnNext signals arrive - // Returns whether more elements are desired or not, and if no more elements are desired, - // for convenience. - protected abstract boolean whenNext(final T element); - - // This method is invoked when the OnComplete signal arrives - // override this method to implement your own custom onComplete logic. - protected void whenComplete() { } - - // This method is invoked if the OnError signal arrives - // override this method to implement your own custom onError logic. - protected void whenError(Throwable error) { } - - private final void handleOnSubscribe(final Subscription s) { - if (s == null) { - // Getting a null `Subscription` here is not valid so lets just ignore it. - } else if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully - try { - s.cancel(); // Cancel the additional subscription to follow rule 2.5 - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } else { - // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber` - // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request` - subscription = s; - try { - // If we want elements, according to rule 2.1 we need to call `request` - // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method - s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } - } - - private final void handleOnNext(final T element) { - if (!done) { // If we aren't already done - if(subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Check for spec violation of 2.1 and 1.09 - (new IllegalStateException("Someone violated the Reactive Streams rule 1.09 and 2.1 by signalling OnNext before `Subscription.request`. (no Subscription)")).printStackTrace(System.err); - } else { - try { - if (whenNext(element)) { - try { - subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } else { - done(); // This is legal according to rule 2.6 - } - } catch(final Throwable t) { - done(); - try { - onError(t); - } catch(final Throwable t2) { - //Subscriber.onError is not allowed to throw an exception, according to rule 2.13 - (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - } - } - } - - // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher` - private void handleOnComplete() { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Publisher is not allowed to signal onComplete before onSubscribe according to rule 1.09 - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err); - } else { - done = true; // Obey rule 2.4 - whenComplete(); - } - } - - // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher` - private void handleOnError(final Throwable error) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Publisher is not allowed to signal onError before onSubscribe according to rule 1.09 - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err); - } else { - done = true; // Obey rule 2.4 - whenError(error); - } - } - - // We implement the OnX methods on `Subscriber` to send Signals that we will process asycnhronously, but only one at a time - - @Override public final void onSubscribe(final Subscription s) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null` - if (s == null) throw null; - - signal(new OnSubscribe(s)); - } - - @Override public final void onNext(final T element) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null` - if (element == null) throw null; - - signal(new OnNext(element)); - } - - @Override public final void onError(final Throwable t) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null` - if (t == null) throw null; - - signal(new OnError(t)); - } - - @Override public final void onComplete() { - signal(OnComplete.Instance); - } - - // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscriber`, like `OnComplete` and `OnNext` , - // and obeying rule 2.11 - private final ConcurrentLinkedQueue inboundSignals = new ConcurrentLinkedQueue(); - - // We are using this `AtomicBoolean` to make sure that this `Subscriber` doesn't run concurrently with itself, - // obeying rule 2.7 and 2.11 - private final AtomicBoolean on = new AtomicBoolean(false); - - @SuppressWarnings("unchecked") - @Override public final void run() { - if(on.get()) { // establishes a happens-before relationship with the end of the previous run - try { - final Signal s = inboundSignals.poll(); // We take a signal off the queue - if (!done) { // If we're done, we shouldn't process any more signals, obeying rule 2.8 - // Below we simply unpack the `Signal`s and invoke the corresponding methods - if (s instanceof OnNext) - handleOnNext(((OnNext)s).next); - else if (s instanceof OnSubscribe) - handleOnSubscribe(((OnSubscribe)s).subscription); - else if (s instanceof OnError) // We are always able to handle OnError, obeying rule 2.10 - handleOnError(((OnError)s).error); - else if (s == OnComplete.Instance) // We are always able to handle OnComplete, obeying rule 2.9 - handleOnComplete(); - } - } finally { - on.set(false); // establishes a happens-before relationship with the beginning of the next run - if(!inboundSignals.isEmpty()) // If we still have signals to process - tryScheduleToExecute(); // Then we try to schedule ourselves to execute again - } - } - } - - // What `signal` does is that it sends signals to the `Subscription` asynchronously - private void signal(final Signal signal) { - if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us - tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already - } - - // This method makes sure that this `Subscriber` is only executing on one Thread at a time - private final void tryScheduleToExecute() { - if(on.compareAndSet(false, true)) { - try { - executor.execute(this); - } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully and not violate rule 2.13 - if (!done) { - try { - done(); // First of all, this failure is not recoverable, so we need to cancel our subscription - } finally { - inboundSignals.clear(); // We're not going to need these anymore - // This subscription is cancelled by now, but letting the Subscriber become schedulable again means - // that we can drain the inboundSignals queue if anything arrives after clearing - on.set(false); - } - } - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java deleted file mode 100644 index 3ac116b6d14..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.example.unicast; - -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.Executor; -import org.reactivestreams.Subscription; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Publisher; - -public class NumberIterablePublisher extends AsyncIterablePublisher { - public NumberIterablePublisher(final int from, final int to, final Executor executor) { - super(new Iterable() { - { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); } - @Override public Iterator iterator() { - return new Iterator() { - private int at = from; - @Override public boolean hasNext() { return at < to; } - @Override public Integer next() { - if (!hasNext()) return Collections.emptyList().iterator().next(); - else return at++; - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java deleted file mode 100644 index 18c13b2aa86..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.example.unicast; - -import org.reactivestreams.*; - -import java.util.concurrent.atomic.AtomicLong; - -/** - * A synchronous implementation of the {@link Publisher} that can - * be subscribed to multiple times and each individual subscription - * will receive range of monotonically increasing integer values on demand. - */ -public final class RangePublisher implements Publisher { - - /** The starting value of the range. */ - final int start; - - /** The number of items to emit. */ - final int count; - - /** - * Constructs a RangePublisher instance with the given start and count values - * that yields a sequence of [start, start + count). - * @param start the starting value of the range - * @param count the number of items to emit - */ - public RangePublisher(int start, int count) { - this.start = start; - this.count = count; - } - - @Override - public void subscribe(Subscriber subscriber) { - // As per rule 1.11, we have decided to support multiple subscribers - // in a unicast configuration for this `Publisher` implementation. - - // As per rule 1.09, we need to throw a `java.lang.NullPointerException` - // if the `Subscriber` is `null` - if (subscriber == null) throw null; - - // As per 2.13, this method must return normally (i.e. not throw). - try { - subscriber.onSubscribe(new RangeSubscription(subscriber, start, start + count)); - } catch (Throwable ex) { - new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 " + - "by throwing an exception from onSubscribe.", ex) - // When onSubscribe fails this way, we don't know what state the - // subscriber is thus calling onError may cause more crashes. - .printStackTrace(); - } - } - - /** - * A Subscription implementation that holds the current downstream - * requested amount and responds to the downstream's request() and - * cancel() calls. - */ - static final class RangeSubscription - // We are using this `AtomicLong` to make sure that this `Subscription` - // doesn't run concurrently with itself, which would violate rule 1.3 - // among others (no concurrent notifications). - // The atomic transition from 0L to N > 0L will ensure this. - extends AtomicLong implements Subscription { - - private static final long serialVersionUID = -9000845542177067735L; - - /** The Subscriber we are emitting integer values to. */ - final Subscriber downstream; - - /** The end index (exclusive). */ - final int end; - - /** - * The current index and within the [start, start + count) range that - * will be emitted as downstream.onNext(). - */ - int index; - - /** - * Indicates the emission should stop. - */ - volatile boolean cancelled; - - /** - * Holds onto the IllegalArgumentException (containing the offending stacktrace) - * indicating there was a non-positive request() call from the downstream. - */ - volatile Throwable invalidRequest; - - /** - * Constructs a stateful RangeSubscription that emits signals to the given - * downstream from an integer range of [start, end). - * @param downstream the Subscriber receiving the integer values and the completion signal. - * @param start the first integer value emitted, start of the range - * @param end the end of the range, exclusive - */ - RangeSubscription(Subscriber downstream, int start, int end) { - this.downstream = downstream; - this.index = start; - this.end = end; - } - - // This method will register inbound demand from our `Subscriber` and - // validate it against rule 3.9 and rule 3.17 - @Override - public void request(long n) { - // Non-positive requests should be honored with IllegalArgumentException - if (n <= 0L) { - invalidRequest = new IllegalArgumentException("§3.9: non-positive requests are not allowed!"); - n = 1; - } - // Downstream requests are cumulative and may come from any thread - for (;;) { - long requested = get(); - long update = requested + n; - // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE` - // we treat the signalled demand as "effectively unbounded" - if (update < 0L) { - update = Long.MAX_VALUE; - } - // atomically update the current requested amount - if (compareAndSet(requested, update)) { - // if there was no prior request amount, we start the emission loop - if (requested == 0L) { - emit(update); - } - break; - } - } - } - - // This handles cancellation requests, and is idempotent, thread-safe and not - // synchronously performing heavy computations as specified in rule 3.5 - @Override - public void cancel() { - // Indicate to the emission loop it should stop. - cancelled = true; - } - - void emit(long currentRequested) { - // Load fields to avoid re-reading them from memory due to volatile accesses in the loop. - Subscriber downstream = this.downstream; - int index = this.index; - int end = this.end; - int emitted = 0; - - try { - for (; ; ) { - // Check if there was an invalid request and then report its exception - // as mandated by rule 3.9. The stacktrace in it should - // help locate the faulty logic in the Subscriber. - Throwable invalidRequest = this.invalidRequest; - if (invalidRequest != null) { - // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6 - cancelled = true; - - downstream.onError(invalidRequest); - return; - } - - // Loop while the index hasn't reached the end and we haven't - // emitted all that's been requested - while (index != end && emitted != currentRequested) { - // to make sure that we follow rule 1.8, 3.6 and 3.7 - // We stop if cancellation was requested. - if (cancelled) { - return; - } - - downstream.onNext(index); - - // Increment the index for the next possible emission. - index++; - // Increment the emitted count to prevent overflowing the downstream. - emitted++; - } - - // If the index reached the end, we complete the downstream. - if (index == end) { - // to make sure that we follow rule 1.8, 3.6 and 3.7 - // Unless cancellation was requested by the last onNext. - if (!cancelled) { - // We need to consider this `Subscription` as cancelled as per rule 1.6 - // Note, however, that this state is not observable from the outside - // world and since we leave the loop with requested > 0L, any - // further request() will never trigger the loop. - cancelled = true; - - downstream.onComplete(); - } - return; - } - - // Did the requested amount change while we were looping? - long freshRequested = get(); - if (freshRequested == currentRequested) { - // Save where the loop has left off: the next value to be emitted - this.index = index; - // Atomically subtract the previously requested (also emitted) amount - currentRequested = addAndGet(-currentRequested); - // If there was no new request in between get() and addAndGet(), we simply quit - // The next 0 to N transition in request() will trigger the next emission loop. - if (currentRequested == 0L) { - break; - } - // Looks like there were more async requests, reset the emitted count and continue. - emitted = 0; - } else { - // Yes, avoid the atomic subtraction and resume. - // emitted != currentRequest in this case and index - // still points to the next value to be emitted - currentRequested = freshRequested; - } - } - } catch (Throwable ex) { - // We can only get here if `onNext`, `onError` or `onComplete` threw, and they - // are not allowed to according to 2.13, so we can only cancel and log here. - // If `onError` throws an exception, this is a spec violation according to rule 1.9, - // and all we can do is to log it. - - // Make sure that we are cancelled, since we cannot do anything else - // since the `Subscriber` is faulty. - cancelled = true; - - // We can't report the failure to onError as the Subscriber is unreliable. - (new IllegalStateException(downstream + " violated the Reactive Streams rule 2.13 by " + - "throwing an exception from onNext, onError or onComplete.", ex)) - .printStackTrace(); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java deleted file mode 100644 index 98817a200d5..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.example.unicast; - -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -/** - * SyncSubscriber is an implementation of Reactive Streams `Subscriber`, - * it runs synchronously (on the Publisher's thread) and requests one element - * at a time and invokes a user-defined method to process each element. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public abstract class SyncSubscriber implements Subscriber { - private Subscription subscription; // Obeying rule 3.1, we make this private! - private boolean done = false; - - @Override public void onSubscribe(final Subscription s) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null` - if (s == null) throw null; - - if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully - try { - s.cancel(); // Cancel the additional subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } else { - // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber` - // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request` - subscription = s; - try { - // If we want elements, according to rule 2.1 we need to call `request` - // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method - s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } - } - - @Override public void onNext(final T element) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onNext prior to onSubscribe.")).printStackTrace(System.err); - } else { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null` - if (element == null) throw null; - - if (!done) { // If we aren't already done - try { - if (whenNext(element)) { - try { - subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch (final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } else { - done(); - } - } catch (final Throwable t) { - done(); - try { - onError(t); - } catch (final Throwable t2) { - //Subscriber.onError is not allowed to throw an exception, according to rule 2.13 - (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - } - } - } - - // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements - // herefor we also need to cancel our `Subscription`. - private void done() { - //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to. - done = true; // If we `whenNext` throws an exception, let's consider ourselves done (not accepting more elements) - try { - subscription.cancel(); // Cancel the subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } - - // This method is left as an exercise to the reader/extension point - // Returns whether more elements are desired or not, and if no more elements are desired - protected abstract boolean whenNext(final T element); - - @Override public void onError(final Throwable t) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err); - } else { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null` - if (t == null) throw null; - // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3 - // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4 - } - } - - @Override public void onComplete() { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err); - } else { - // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3 - // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4 - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java deleted file mode 100644 index 25a99ec9a8d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (c) 2019, 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 org.reactivestreams.tck; - -import org.reactivestreams.Processor; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.ManualPublisher; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.TestEnvironment.Promise; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.HashSet; -import java.util.Set; - -public abstract class IdentityProcessorVerification extends WithHelperPublisher - implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules { - - private final TestEnvironment env; - - ////////////////////// DELEGATED TO SPECS ////////////////////// - - // for delegating tests - private final SubscriberWhiteboxVerification subscriberVerification; - - // for delegating tests - private final PublisherVerification publisherVerification; - - ////////////////// END OF DELEGATED TO SPECS ////////////////// - - // number of elements the processor under test must be able ot buffer, - // without dropping elements. Defaults to `TestEnvironment.TEST_BUFFER_SIZE`. - private final int processorBufferSize; - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements. - */ - @SuppressWarnings("unused") - public IdentityProcessorVerification(final TestEnvironment env) { - this(env, PublisherVerification.envPublisherReferenceGCTimeoutMillis(), TestEnvironment.TEST_BUFFER_SIZE); - } - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - */ - @SuppressWarnings("unused") - public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - this(env, publisherReferenceGCTimeoutMillis, TestEnvironment.TEST_BUFFER_SIZE); - } - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - * @param processorBufferSize number of elements the processor is required to be able to buffer. - */ - public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) { - this.env = env; - this.processorBufferSize = processorBufferSize; - - this.subscriberVerification = new SubscriberWhiteboxVerification(env) { - @Override - public Subscriber createSubscriber(WhiteboxSubscriberProbe probe) { - return IdentityProcessorVerification.this.createSubscriber(probe); - } - - @Override public T createElement(int element) { - return IdentityProcessorVerification.this.createElement(element); - } - - @Override - public Publisher createHelperPublisher(long elements) { - return IdentityProcessorVerification.this.createHelperPublisher(elements); - } - }; - - publisherVerification = new PublisherVerification(env, publisherReferenceGCTimeoutMillis) { - @Override - public Publisher createPublisher(long elements) { - return IdentityProcessorVerification.this.createPublisher(elements); - } - - @Override - public Publisher createFailedPublisher() { - return IdentityProcessorVerification.this.createFailedPublisher(); - } - - @Override - public long maxElementsFromPublisher() { - return IdentityProcessorVerification.this.maxElementsFromPublisher(); - } - - @Override - public long boundedDepthOfOnNextAndRequestRecursion() { - return IdentityProcessorVerification.this.boundedDepthOfOnNextAndRequestRecursion(); - } - - @Override - public boolean skipStochasticTests() { - return IdentityProcessorVerification.this.skipStochasticTests(); - } - }; - } - - /** - * This is the main method you must implement in your test incarnation. - * It must create a {@link Processor}, which simply forwards all stream elements from its upstream - * to its downstream. It must be able to internally buffer the given number of elements. - * - * @param bufferSize number of elements the processor is required to be able to buffer. - */ - public abstract Processor createIdentityProcessor(int bufferSize); - - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you want to ignore these additional tests, return {@code null} from this method. - */ - public abstract Publisher createFailedPublisher(); - - /** - * Override and return lower value if your Publisher is only able to produce a known number of elements. - * For example, if it is designed to return at-most-one element, return {@code 1} from this method. - * - * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements. - * - * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE}, - * which will result in *skipping all tests which require an onComplete to be triggered* (!). - */ - public long maxElementsFromPublisher() { - return Long.MAX_VALUE - 1; - } - - /** - * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a - * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of - * recursive calls to exceed the number returned by this method. - * - * @see reactive streams spec, rule 3.3 - * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion() - */ - public long boundedDepthOfOnNextAndRequestRecursion() { - return 1; - } - - /** - * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}. - * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify— - * usually this means that this test case can yield false positives ("be green") even if for some case, - * the given implementation may violate the tested behaviour. - */ - public boolean skipStochasticTests() { - return false; - } - - /** - * Describes the tested implementation in terms of how many subscribers they can support. - * Some tests require the {@code Publisher} under test to support multiple Subscribers, - * yet the spec does not require all publishers to be able to do so, thus – if an implementation - * supports only a limited number of subscribers (e.g. only 1 subscriber, also known as "no fanout") - * you MUST return that number from this method by overriding it. - */ - public long maxSupportedSubscribers() { - return Long.MAX_VALUE; - } - - /** - * Override this method and return {@code true} if the {@link Processor} returned by the - * {@link #createIdentityProcessor(int)} coordinates its {@link Subscriber}s - * request amounts and only delivers onNext signals if all Subscribers have - * indicated (via their Subscription#request(long)) they are ready to receive elements. - */ - public boolean doesCoordinatedEmission() { - return false; - } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - publisherVerification.setUp(); - subscriberVerification.setUp(); - } - - ////////////////////// PUBLISHER RULES VERIFICATION /////////////////////////// - - // A Processor - // must obey all Publisher rules on its publishing side - public Publisher createPublisher(long elements) { - final Processor processor = createIdentityProcessor(processorBufferSize); - final Publisher pub = createHelperPublisher(elements); - pub.subscribe(processor); - return processor; // we run the PublisherVerification against this - } - - @Override @Test - public void required_validate_maxElementsFromPublisher() throws Exception { - publisherVerification.required_validate_maxElementsFromPublisher(); - } - - @Override @Test - public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception { - publisherVerification.required_validate_boundedDepthOfOnNextAndRequestRecursion(); - } - - /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" PUBLISHER ////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - @Test - public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable { - publisherVerification.required_createPublisher1MustProduceAStreamOfExactly1Element(); - } - - @Test - public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable { - publisherVerification.required_createPublisher3MustProduceAStreamOfExactly3Elements(); - } - - @Override @Test - public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable { - publisherVerification.required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements(); - } - - @Override @Test - public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable { - publisherVerification.required_spec102_maySignalLessThanRequestedAndTerminateSubscription(); - } - - @Override @Test - public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable { - publisherVerification.stochastic_spec103_mustSignalOnMethodsSequentially(); - } - - @Override @Test - public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable { - publisherVerification.optional_spec104_mustSignalOnErrorWhenFails(); - } - - @Override @Test - public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable { - publisherVerification.required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates(); - } - - @Override @Test - public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable { - publisherVerification.optional_spec105_emptyStreamMustTerminateBySignallingOnComplete(); - } - - @Override @Test - public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable { - publisherVerification.untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled(); - } - - @Override @Test - public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable { - publisherVerification.required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled(); - } - - @Override @Test - public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable { - publisherVerification.untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled(); - } - - @Override @Test - public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable { - publisherVerification.untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals(); - } - - @Override @Test - public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable { - publisherVerification.untested_spec109_subscribeShouldNotThrowNonFatalThrowable(); - } - - @Override @Test - public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable { - publisherVerification.required_spec109_subscribeThrowNPEOnNullSubscriber(); - } - - @Override @Test - public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable { - publisherVerification.required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe(); - } - - @Override @Test - public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable { - publisherVerification.required_spec109_mustIssueOnSubscribeForNonNullSubscriber(); - } - - @Override @Test - public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable { - publisherVerification.untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice(); - } - - @Override @Test - public void optional_spec111_maySupportMultiSubscribe() throws Throwable { - publisherVerification.optional_spec111_maySupportMultiSubscribe(); - } - - @Override @Test - public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable { - publisherVerification.optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected(); - } - - @Override @Test - public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable { - publisherVerification.required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe(); - } - - @Override @Test - public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable { - publisherVerification.required_spec303_mustNotAllowUnboundedRecursion(); - } - - @Override @Test - public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception { - publisherVerification.untested_spec304_requestShouldNotPerformHeavyComputations(); - } - - @Override @Test - public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception { - publisherVerification.untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation(); - } - - @Override @Test - public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable { - publisherVerification.required_spec306_afterSubscriptionIsCancelledRequestMustBeNops(); - } - - @Override @Test - public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable { - publisherVerification.required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops(); - } - - @Override @Test - public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable { - publisherVerification.required_spec309_requestZeroMustSignalIllegalArgumentException(); - } - - @Override @Test - public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable { - publisherVerification.required_spec309_requestNegativeNumberMustSignalIllegalArgumentException(); - } - - @Override @Test - public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable { - publisherVerification.optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage(); - } - - @Override @Test - public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable { - publisherVerification.required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling(); - } - - @Override @Test - public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable { - publisherVerification.required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber(); - } - - @Override @Test - public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustSupportAPendingElementCountUpToLongMaxValue(); - } - - @Override @Test - public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue(); - } - - @Override @Test - public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue(); - } - - - /** - * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks if two {@code Subscriber}s - * receive the same items and a terminal {@code Exception}. - *

    - * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested, - * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property. - *

    - * Verifies rule: 1.4 with multiple - * {@code Subscriber}s. - *

    - * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2. - *

    - * If this test fails, the following could be checked within the {@code Processor} implementation: - *

      - *
    • The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.
    • - *
    • The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or - * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s - * both have to request first.
    • - *
    - */ - @Test - public void required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANonRecoverableError() throws Throwable { - optionalMultipleSubscribersTest(2, new Function() { - @Override - public TestSetup apply(Long aLong) throws Throwable { - return new TestSetup(env, processorBufferSize) {{ - final ManualSubscriberWithErrorCollection sub1 = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub1); - - final ManualSubscriberWithErrorCollection sub2 = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub2); - - final Exception ex = new RuntimeException("Test exception"); - - if (doesCoordinatedEmission()) { - sub1.request(1); - sub2.request(1); - - expectRequest(); - - final T x = sendNextTFromUpstream(); - - expectNextElement(sub1, x); - expectNextElement(sub2, x); - - sub1.request(1); - sub2.request(1); - } else { - sub1.request(1); - - expectRequest(env.defaultTimeoutMillis(), - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - - final T x = sendNextTFromUpstream(); - expectNextElement(sub1, x, - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - - sub1.request(1); - - // sub1 has received one element, and has one demand pending - // sub2 has not yet requested anything - } - sendError(ex); - - sub1.expectError(ex); - sub2.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - }); - } - - ////////////////////// SUBSCRIBER RULES VERIFICATION /////////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - // A Processor - // must obey all Subscriber rules on its consuming side - public Subscriber createSubscriber(final SubscriberWhiteboxVerification.WhiteboxSubscriberProbe probe) { - final Processor processor = createIdentityProcessor(processorBufferSize); - processor.subscribe( - new Subscriber() { - private final Promise subs = new Promise(env); - - @Override - public void onSubscribe(final Subscription subscription) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onSubscribe(%s)", subscription)); - } - if (subs.isCompleted()) subscription.cancel(); // the Probe must also pass subscriber verification - - probe.registerOnSubscribe(new SubscriberWhiteboxVerification.SubscriberPuppet() { - - @Override - public void triggerRequest(long elements) { - subscription.request(elements); - } - - @Override - public void signalCancel() { - subscription.cancel(); - } - }); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onNext(%s)", element)); - } - probe.registerOnNext(element); - } - - @Override - public void onComplete() { - if (env.debugEnabled()) { - env.debug("whiteboxSubscriber::onComplete()"); - } - probe.registerOnComplete(); - } - - @Override - public void onError(Throwable cause) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onError(%s)", cause)); - } - probe.registerOnError(cause); - } - }); - - return processor; // we run the SubscriberVerification against this - } - - ////////////////////// OTHER RULE VERIFICATION /////////////////////////// - - // A Processor - // must immediately pass on `onError` events received from its upstream to its downstream - @Test - public void mustImmediatelyPassOnOnErrorEventsReceivedFromItsUpstreamToItsDownstream() throws Exception { - new TestSetup(env, processorBufferSize) {{ - final ManualSubscriberWithErrorCollection sub = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub); - - final Exception ex = new RuntimeException("Test exception"); - sendError(ex); - sub.expectError(ex); // "immediately", i.e. without a preceding request - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - - /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" SUBSCRIBER ////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - @Test - public void required_exerciseWhiteboxHappyPath() throws Throwable { - subscriberVerification.required_exerciseWhiteboxHappyPath(); - } - - @Override @Test - public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable { - subscriberVerification.required_spec201_mustSignalDemandViaSubscriptionRequest(); - } - - @Override @Test - public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception { - subscriberVerification.untested_spec202_shouldAsynchronouslyDispatch(); - } - - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete(); - } - - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError(); - } - - @Override @Test - public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - subscriberVerification.untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError(); - } - - @Override @Test - public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable { - subscriberVerification.required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal(); - } - - @Override @Test - public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - subscriberVerification.untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid(); - } - - @Override @Test - public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - subscriberVerification.untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization(); - } - - @Override @Test - public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - subscriberVerification.required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel(); - } - - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall(); - } - - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall(); - } - - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall(); - } - - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall(); - } - - @Override @Test - public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - subscriberVerification.untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents(); - } - - @Override @Test - public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable { - subscriberVerification.untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation(); - } - - @Override @Test - public void untested_spec213_failingOnSignalInvocation() throws Exception { - subscriberVerification.untested_spec213_failingOnSignalInvocation(); - } - - @Override @Test - public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - @Override @Test - public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - @Override @Test - public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - - @Override @Test - public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception { - subscriberVerification.untested_spec301_mustNotBeCalledOutsideSubscriberContext(); - } - - @Override @Test - public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - subscriberVerification.required_spec308_requestMustRegisterGivenNumberElementsToBeProduced(); - } - - @Override @Test - public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - subscriberVerification.untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber(); - } - - @Override @Test - public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - subscriberVerification.untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError(); - } - - @Override @Test - public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - subscriberVerification.untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists(); - } - - @Override @Test - public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - subscriberVerification.untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError(); - } - - @Override @Test - public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - subscriberVerification.untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber(); - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS ////////////////////// - - /** - * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks requests - * from {@code Subscriber}s will eventually lead to requests towards the upstream of the {@code Processor}. - *

    - * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested, - * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property. - *

    - * Verifies rule: 2.1 with multiple - * {@code Subscriber}s. - *

    - * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2. - *

    - * If this test fails, the following could be checked within the {@code Processor} implementation: - *

      - *
    • The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.
    • - *
    • The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or - * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s - * both have to request first.
    • - *
    - */ - @Test - public void required_mustRequestFromUpstreamForElementsThatHaveBeenRequestedLongAgo() throws Throwable { - optionalMultipleSubscribersTest(2, new Function() { - @Override - public TestSetup apply(Long subscribers) throws Throwable { - return new TestSetup(env, processorBufferSize) {{ - ManualSubscriber sub1 = newSubscriber(); - sub1.request(20); - - long totalRequests = expectRequest(); - final T x = sendNextTFromUpstream(); - expectNextElement(sub1, x); - - if (totalRequests == 1) { - totalRequests += expectRequest(); - } - final T y = sendNextTFromUpstream(); - expectNextElement(sub1, y); - - if (totalRequests == 2) { - totalRequests += expectRequest(); - } - - final ManualSubscriber sub2 = newSubscriber(); - - // sub1 now has 18 pending - // sub2 has 0 pending - - if (doesCoordinatedEmission()) { - sub2.expectNone(); // since sub2 hasn't requested anything yet - - sub2.request(1); - - final T z = sendNextTFromUpstream(); - expectNextElement(sub1, z); - expectNextElement(sub2, z); - } else { - final T z = sendNextTFromUpstream(); - expectNextElement(sub1, z, - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - sub2.expectNone(); // since sub2 hasn't requested anything yet - - sub2.request(1); - expectNextElement(sub2, z); - } - if (totalRequests == 3) { - expectRequest(); - } - - // to avoid error messages during test harness shutdown - sendCompletion(); - sub1.expectCompletion(env.defaultTimeoutMillis()); - sub2.expectCompletion(env.defaultTimeoutMillis()); - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - }); - } - - /////////////////////// TEST INFRASTRUCTURE ////////////////////// - - public void notVerified() { - publisherVerification.notVerified(); - } - - public void notVerified(String message) { - publisherVerification.notVerified(message); - } - - /** - * Test for feature that REQUIRES multiple subscribers to be supported by Publisher. - */ - public void optionalMultipleSubscribersTest(long requiredSubscribersSupport, Function body) throws Throwable { - if (requiredSubscribersSupport > maxSupportedSubscribers()) - notVerified(String.format("The Publisher under test only supports %d subscribers, while this test requires at least %d to run.", - maxSupportedSubscribers(), requiredSubscribersSupport)); - else body.apply(requiredSubscribersSupport); - } - - public abstract class TestSetup extends ManualPublisher { - final private ManualSubscriber tees; // gives us access to an infinite stream of T values - private Set seenTees = new HashSet(); - - final Processor processor; - - public TestSetup(TestEnvironment env, int testBufferSize) throws InterruptedException { - super(env); - tees = env.newManualSubscriber(createHelperPublisher(Long.MAX_VALUE)); - processor = createIdentityProcessor(testBufferSize); - subscribe(processor); - } - - public ManualSubscriber newSubscriber() throws InterruptedException { - return env.newManualSubscriber(processor); - } - - public T nextT() throws InterruptedException { - final T t = tees.requestNextElement(); - if (seenTees.contains(t)) { - env.flop(String.format("Helper publisher illegally produced the same element %s twice", t)); - } - seenTees.add(t); - return t; - } - - public void expectNextElement(ManualSubscriber sub, T expected) throws InterruptedException { - final T elem = sub.nextElement(String.format("timeout while awaiting %s", expected)); - if (!elem.equals(expected)) { - env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected)); - } - } - - public void expectNextElement(ManualSubscriber sub, T expected, String errorMessageAddendum) throws InterruptedException { - final T elem = sub.nextElement(String.format("timeout while awaiting %s. %s", expected, errorMessageAddendum)); - if (!elem.equals(expected)) { - env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected)); - } - } - - public T sendNextTFromUpstream() throws InterruptedException { - final T x = nextT(); - sendNext(x); - return x; - } - } - - public class ManualSubscriberWithErrorCollection extends ManualSubscriberWithSubscriptionSupport { - Promise error; - - public ManualSubscriberWithErrorCollection(TestEnvironment env) { - super(env); - error = new Promise(env); - } - - @Override - public void onError(Throwable cause) { - error.complete(cause); - } - - public void expectError(Throwable cause) throws InterruptedException { - expectError(cause, env.defaultTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectError(Throwable cause, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, "Did not receive expected error on downstream"); - if (!cause.equals(error.value())) { - env.flop(String.format("Expected error %s but got %s", cause, error.value())); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java deleted file mode 100644 index fdfd24582ef..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java +++ /dev/null @@ -1,1245 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.BlackholeSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.TestEnvironment.Latch; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; -import org.testng.SkipException; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.lang.Override; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -/** - * Provides tests for verifying {@code Publisher} specification rules. - * - * @see org.reactivestreams.Publisher - */ -public abstract class PublisherVerification implements PublisherVerificationRules { - - private static final String PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV = "PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS"; - private static final long DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS = 300L; - - private final TestEnvironment env; - - /** - * The amount of time after which a cancelled Subscriber reference should be dropped. - * See Rule 3.13 for details. - */ - private final long publisherReferenceGCTimeoutMillis; - - /** - * Constructs a new verification class using the given env and configuration. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - */ - public PublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - this.env = env; - this.publisherReferenceGCTimeoutMillis = publisherReferenceGCTimeoutMillis; - } - - /** - * Constructs a new verification class using the given env and configuration. - * - * The value for {@code publisherReferenceGCTimeoutMillis} will be obtained by using {@link PublisherVerification#envPublisherReferenceGCTimeoutMillis()}. - */ - public PublisherVerification(TestEnvironment env) { - this.env = env; - this.publisherReferenceGCTimeoutMillis = envPublisherReferenceGCTimeoutMillis(); - } - - /** - * Tries to parse the env variable {@code PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS} as long and returns the value if present, - * OR its default value ({@link PublisherVerification#DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS}). - * - * This value is used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envPublisherReferenceGCTimeoutMillis() { - final String envMillis = System.getenv(PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS; - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * This is the main method you must implement in your test incarnation. - * It must create a Publisher for a stream with exactly the given number of elements. - * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite. - */ - public abstract Publisher createPublisher(long elements); - - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you ignore these additional tests, return {@code null} from this method. - */ - public abstract Publisher createFailedPublisher(); - - - /** - * Override and return lower value if your Publisher is only able to produce a known number of elements. - * For example, if it is designed to return at-most-one element, return {@code 1} from this method. - * - * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements. - * - * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE}, - * which will result in *skipping all tests which require an onComplete to be triggered* (!). - */ - public long maxElementsFromPublisher() { - return Long.MAX_VALUE - 1; - } - - /** - * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}. - * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify— - * usually this means that this test case can yield false positives ("be green") even if for some case, - * the given implementation may violate the tested behaviour. - */ - public boolean skipStochasticTests() { - return false; - } - - /** - * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a - * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of - * recursive calls to exceed the number returned by this method. - * - * @see reactive streams spec, rule 3.3 - * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion() - */ - public long boundedDepthOfOnNextAndRequestRecursion() { - return 1; - } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// TEST SETUP VERIFICATION ////////////////////////////// - - @Override @Test - public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable { - activePublisherTest(1, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub = env.newManualSubscriber(pub); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub)); - sub.requestEndOfStream(); - } - - Optional requestNextElementOrEndOfStream(Publisher pub, ManualSubscriber sub) throws InterruptedException { - return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub)); - } - - }); - } - - @Override @Test - public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable { - activePublisherTest(3, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub = env.newManualSubscriber(pub); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub)); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 1 element", pub)); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 2 elements", pub)); - sub.requestEndOfStream(); - } - - Optional requestNextElementOrEndOfStream(Publisher pub, ManualSubscriber sub) throws InterruptedException { - return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub)); - } - - }); - } - - @Override @Test - public void required_validate_maxElementsFromPublisher() throws Exception { - assertTrue(maxElementsFromPublisher() >= 0, "maxElementsFromPublisher MUST return a number >= 0"); - } - - @Override @Test - public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception { - assertTrue(boundedDepthOfOnNextAndRequestRecursion() >= 1, "boundedDepthOfOnNextAndRequestRecursion must return a number >= 1"); - } - - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - @Override @Test - public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable { - activePublisherTest(5, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - - ManualSubscriber sub = env.newManualSubscriber(pub); - try { - sub.expectNone(String.format("Publisher %s produced value before the first `request`: ", pub)); - sub.request(1); - sub.nextElement(String.format("Publisher %s produced no element after first `request`", pub)); - sub.expectNone(String.format("Publisher %s produced unrequested: ", pub)); - - sub.request(1); - sub.request(2); - sub.nextElements(3, env.defaultTimeoutMillis(), String.format("Publisher %s produced less than 3 elements after two respective `request` calls", pub)); - - sub.expectNone(String.format("Publisher %sproduced unrequested ", pub)); - } finally { - sub.cancel(); - } - } - }); - } - - @Override @Test - public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable { - final int elements = 3; - final int requested = 10; - - activePublisherTest(elements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(requested); - sub.nextElements(elements); - sub.expectCompletion(); - } - }); - } - - @Override @Test - public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable { - final int iterations = 100; - final int elements = 10; - - stochasticTest(iterations, new Function() { - @Override - public Void apply(final Integer runNumber) throws Throwable { - activePublisherTest(elements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch completionLatch = new Latch(env); - - final AtomicInteger gotElements = new AtomicInteger(0); - pub.subscribe(new Subscriber() { - private Subscription subs; - - private ConcurrentAccessBarrier concurrentAccessBarrier = new ConcurrentAccessBarrier(); - - /** - * Concept wise very similar to a {@link org.reactivestreams.tck.TestEnvironment.Latch}, serves to protect - * a critical section from concurrent access, with the added benefit of Thread tracking and same-thread-access awareness. - * - * Since a Synchronous Publisher may choose to synchronously (using the same {@link Thread}) call - * {@code onNext} directly from either {@code subscribe} or {@code request} a plain Latch is not enough - * to verify concurrent access safety - one needs to track if the caller is not still using the calling thread - * to enter subsequent critical sections ("nesting" them effectively). - */ - final class ConcurrentAccessBarrier { - private AtomicReference currentlySignallingThread = new AtomicReference(null); - private volatile String previousSignal = null; - - public void enterSignal(String signalName) { - if((!currentlySignallingThread.compareAndSet(null, Thread.currentThread())) && !isSynchronousSignal()) { - env.flop(String.format( - "Illegal concurrent access detected (entering critical section)! " + - "%s emited %s signal, before %s finished its %s signal.", - Thread.currentThread(), signalName, currentlySignallingThread.get(), previousSignal)); - } - this.previousSignal = signalName; - } - - public void leaveSignal(String signalName) { - currentlySignallingThread.set(null); - this.previousSignal = signalName; - } - - private boolean isSynchronousSignal() { - return (previousSignal != null) && Thread.currentThread().equals(currentlySignallingThread.get()); - } - - } - - @Override - public void onSubscribe(Subscription s) { - final String signal = "onSubscribe()"; - concurrentAccessBarrier.enterSignal(signal); - - subs = s; - subs.request(1); - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onNext(T ignore) { - final String signal = String.format("onNext(%s)", ignore); - concurrentAccessBarrier.enterSignal(signal); - - if (gotElements.incrementAndGet() <= elements) // requesting one more than we know are in the stream (some Publishers need this) - subs.request(1); - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onError(Throwable t) { - final String signal = String.format("onError(%s)", t.getMessage()); - concurrentAccessBarrier.enterSignal(signal); - - // ignore value - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onComplete() { - final String signal = "onComplete()"; - concurrentAccessBarrier.enterSignal(signal); - - // entering for completeness - - concurrentAccessBarrier.leaveSignal(signal); - completionLatch.close(); - } - }); - - completionLatch.expectClose( - elements * env.defaultTimeoutMillis(), - String.format("Failed in iteration %d of %d. Expected completion signal after signalling %d elements (signalled %d), yet did not receive it", - runNumber, iterations, elements, gotElements.get())); - } - }); - return null; - } - }); - } - - @Override @Test - public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable { - try { - whenHasErrorPublisherTest(new PublisherTestRun() { - @Override - public void run(final Publisher pub) throws InterruptedException { - final Latch onErrorlatch = new Latch(env); - final Latch onSubscribeLatch = new Latch(env); - pub.subscribe(new TestEnvironment.TestSubscriber(env) { - @Override - public void onSubscribe(Subscription subs) { - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - onErrorlatch.assertOpen(String.format("Error-state Publisher %s called `onError` twice on new Subscriber", pub)); - onErrorlatch.close(); - } - }); - - onSubscribeLatch.expectClose("Should have received onSubscribe"); - onErrorlatch.expectClose(String.format("Error-state Publisher %s did not call `onError` on new Subscriber", pub)); - - env.verifyNoAsyncErrors(); - } - }); - } catch (SkipException se) { - throw se; - } catch (Throwable ex) { - // we also want to catch AssertionErrors and anything the publisher may have thrown inside subscribe - // which was wrong of him - he should have signalled on error using onError - throw new RuntimeException(String.format("Publisher threw exception (%s) instead of signalling error via onError!", ex.getMessage()), ex); - } - } - - @Override @Test - public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable { - activePublisherTest(3, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.requestNextElement(); - sub.requestNextElement(); - sub.requestNextElement(); - sub.requestEndOfStream(); - sub.expectNone(); - } - }); - } - - @Override @Test - public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable { - optionalActivePublisherTest(0, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(1); - sub.expectCompletion(); - sub.expectNone(); - } - }); - } - - @Override @Test - public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable { - notVerified(); // not really testable without more control over the Publisher - } - - @Override @Test - public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable { - activePublisherTest(1, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(10); - sub.nextElement(); - sub.expectCompletion(); - - sub.request(10); - sub.expectNone(); - } - }); - } - - @Override @Test - public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable { - notVerified(); // can we meaningfully test this, without more control over the publisher? - } - - @Override @Test - public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - @Override @Test - public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - @Override @Test - public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable { - activePublisherTest(0, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - try { - pub.subscribe(null); - env.flop("Publisher did not throw a NullPointerException when given a null Subscribe in subscribe"); - } catch (NullPointerException ignored) { - // valid behaviour - } - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable { - activePublisherTest(0, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch onSubscribeLatch = new Latch(env); - final AtomicReference cancel = new AtomicReference(); - try { - pub.subscribe(new Subscriber() { - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - } - - @Override - public void onSubscribe(Subscription subs) { - cancel.set(subs); - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - - @Override - public void onNext(T elem) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onNext always"); - } - - @Override - public void onComplete() { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onComplete always"); - } - }); - onSubscribeLatch.expectClose("Should have received onSubscribe"); - env.verifyNoAsyncErrorsNoDelay(); - } finally { - Subscription s = cancel.getAndSet(null); - if (s != null) { - s.cancel(); - } - } - } - }); - } - - @Override @Test - public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable { - whenHasErrorPublisherTest(new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch onErrorLatch = new Latch(env); - final Latch onSubscribeLatch = new Latch(env); - ManualSubscriberWithSubscriptionSupport sub = new ManualSubscriberWithSubscriptionSupport(env) { - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - onErrorLatch.assertOpen("Only one onError call expected"); - onErrorLatch.close(); - } - - @Override - public void onSubscribe(Subscription subs) { - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - }; - pub.subscribe(sub); - onSubscribeLatch.expectClose("Should have received onSubscribe"); - onErrorLatch.expectClose("Should have received onError"); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#1.11 - @Override @Test - public void optional_spec111_maySupportMultiSubscribe() throws Throwable { - optionalActivePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - - try { - env.verifyNoAsyncErrors(); - } finally { - try { - sub1.cancel(); - } finally { - sub2.cancel(); - } - } - } - }); - } - - @Override @Test - public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable { - optionalActivePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - // Since we're testing the case when the Publisher DOES support the optional multi-subscribers scenario, - // and decides if it handles them uni-cast or multi-cast, we don't know which subscriber will receive an - // onNext (and optional onComplete) signal(s) and which just onComplete signal. - // Plus, even if subscription assumed to be unicast, it's implementation choice, which one will be signalled - // with onNext. - sub1.requestNextElementOrEndOfStream(); - sub2.requestNextElementOrEndOfStream(); - try { - env.verifyNoAsyncErrors(); - } finally { - try { - sub1.cancel(); - } finally { - sub2.cancel(); - } - } - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable { - optionalActivePublisherTest(5, true, new PublisherTestRun() { // This test is skipped if the publisher is unbounded (never sends onComplete) - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - sub1.request(1); - T x1 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub2.request(2); - List y1 = sub2.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 2nd subscriber", pub)); - sub1.request(1); - T x2 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub3.request(3); - List z1 = sub3.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 3rd subscriber", pub)); - sub3.request(1); - T z2 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub)); - sub3.request(1); - T z3 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub)); - sub3.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 3rd subscriber", pub)); - sub2.request(3); - List y2 = sub2.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 2nd subscriber", pub)); - sub2.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 2nd subscriber", pub)); - sub1.request(2); - List x3 = sub1.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 1st subscriber", pub)); - sub1.request(1); - T x4 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub1.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 1st subscriber", pub)); - - @SuppressWarnings("unchecked") - List r = new ArrayList(Arrays.asList(x1, x2)); - r.addAll(x3); - r.addAll(Collections.singleton(x4)); - - List check1 = new ArrayList(y1); - check1.addAll(y2); - - //noinspection unchecked - List check2 = new ArrayList(z1); - check2.add(z2); - check2.add(z3); - - assertEquals(r, check1, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 2", pub)); - assertEquals(r, check2, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 3", pub)); - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable { - optionalActivePublisherTest(3, false, new PublisherTestRun() { // This test is skipped if the publisher cannot produce enough elements - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - List received1 = new ArrayList(); - List received2 = new ArrayList(); - List received3 = new ArrayList(); - - // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains... - // edgy edge case? - sub1.request(4); - sub2.request(4); - sub3.request(4); - - received1.addAll(sub1.nextElements(3)); - received2.addAll(sub2.nextElements(3)); - received3.addAll(sub3.nextElements(3)); - - // NOTE: can't check completion, the Publisher may not be able to signal it - // a similar test *with* completion checking is implemented - - assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers")); - assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers")); - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable { - optionalActivePublisherTest(3, true, new PublisherTestRun() { // This test is skipped if the publisher is unbounded (never sends onComplete) - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - List received1 = new ArrayList(); - List received2 = new ArrayList(); - List received3 = new ArrayList(); - - // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains... - // edgy edge case? - sub1.request(4); - sub2.request(4); - sub3.request(4); - - received1.addAll(sub1.nextElements(3)); - received2.addAll(sub2.nextElements(3)); - received3.addAll(sub3.nextElements(3)); - - sub1.expectCompletion(); - sub2.expectCompletion(); - sub3.expectCompletion(); - - assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers")); - assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers")); - } - }); - } - - ///////////////////// SUBSCRIPTION TESTS ////////////////////////////////// - - @Override @Test - public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable { - activePublisherTest(6, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = new ManualSubscriber(env) { - @Override - public void onSubscribe(Subscription subs) { - this.subscription.completeImmediatly(subs); - - subs.request(1); - subs.request(1); - subs.request(1); - } - - @Override - public void onNext(T element) { - Subscription subs = this.subscription.value(); - subs.request(1); - } - }; - - env.subscribe(pub, sub); - - env.verifyNoAsyncErrors(); - } - }); - } - - @Override @Test - public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable { - final long oneMoreThanBoundedLimit = boundedDepthOfOnNextAndRequestRecursion() + 1; - - activePublisherTest(oneMoreThanBoundedLimit, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ThreadLocal stackDepthCounter = new ThreadLocal() { - @Override - protected Long initialValue() { - return 0L; - } - }; - - final Latch runCompleted = new Latch(env); - - final ManualSubscriber sub = new ManualSubscriberWithSubscriptionSupport(env) { - // counts the number of signals received, used to break out from possibly infinite request/onNext loops - long signalsReceived = 0L; - - @Override - public void onNext(T element) { - // NOT calling super.onNext as this test only cares about stack depths, not the actual values of elements - // which also simplifies this test as we do not have to drain the test buffer, which would otherwise be in danger of overflowing - - signalsReceived += 1; - stackDepthCounter.set(stackDepthCounter.get() + 1); - if (env.debugEnabled()) { - env.debug(String.format("%s(recursion depth: %d)::onNext(%s)", this, stackDepthCounter.get(), element)); - } - - final long callsUntilNow = stackDepthCounter.get(); - if (callsUntilNow > boundedDepthOfOnNextAndRequestRecursion()) { - env.flop(String.format("Got %d onNext calls within thread: %s, yet expected recursive bound was %d", - callsUntilNow, Thread.currentThread(), boundedDepthOfOnNextAndRequestRecursion())); - - // stop the recursive call chain - runCompleted.close(); - return; - } else if (signalsReceived >= oneMoreThanBoundedLimit) { - // since max number of signals reached, and recursion depth not exceeded, we judge this as a success and - // stop the recursive call chain - runCompleted.close(); - return; - } - - // request more right away, the Publisher must break the recursion - subscription.value().request(1); - - stackDepthCounter.set(stackDepthCounter.get() - 1); - } - - @Override - public void onComplete() { - super.onComplete(); - runCompleted.close(); - } - - @Override - public void onError(Throwable cause) { - super.onError(cause); - runCompleted.close(); - } - }; - - try { - env.subscribe(pub, sub); - - sub.request(1); // kick-off the `request -> onNext -> request -> onNext -> ...` - - final String msg = String.format("Unable to validate call stack depth safety, " + - "awaited at-most %s signals (`maxOnNextSignalsInRecursionTest()`) or completion", - oneMoreThanBoundedLimit); - runCompleted.expectClose(env.defaultTimeoutMillis(), msg); - env.verifyNoAsyncErrorsNoDelay(); - } finally { - // since the request/onNext recursive calls may keep the publisher running "forever", - // we MUST cancel it manually before exiting this test case - sub.cancel(); - } - } - }); - } - - @Override @Test - public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable { - activePublisherTest(3, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - - // override ManualSubscriberWithSubscriptionSupport#cancel because by default a ManualSubscriber will drop the - // subscription once it's cancelled (as expected). - // In this test however it must keep the cancelled Subscription and keep issuing `request(long)` to it. - ManualSubscriber sub = new ManualSubscriberWithSubscriptionSupport(env) { - @Override - public void cancel() { - if (subscription.isCompleted()) { - subscription.value().cancel(); - } else { - env.flop("Cannot cancel a subscription before having received it"); - } - } - }; - - env.subscribe(pub, sub); - - sub.cancel(); - sub.request(1); - sub.request(1); - sub.request(1); - - sub.expectNone(); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable { - activePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - - // leak the Subscription - final Subscription subs = sub.subscription.value(); - - subs.cancel(); - subs.cancel(); - subs.cancel(); - - sub.expectNone(); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable { - activePublisherTest(10, false, new PublisherTestRun() { - @Override public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(0); - sub.expectError(IllegalArgumentException.class); - } - }); - } - - @Override @Test - public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable { - activePublisherTest(10, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final Random r = new Random(); - sub.request(-r.nextInt(Integer.MAX_VALUE) - 1); - // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem - sub.expectError(IllegalArgumentException.class); - } - }); - } - - @Override @Test - public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable { - optionalActivePublisherTest(10, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final Random r = new Random(); - sub.request(-r.nextInt(Integer.MAX_VALUE) - 1); - // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem - sub.expectErrorWithMessage(IllegalArgumentException.class, Arrays.asList("3.9", "non-positive subscription request", "negative subscription request")); - } - }); - } - - @Override @Test - public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable { - // the publisher is able to signal more elements than the subscriber will be requesting in total - final int publisherElements = 20; - - final int demand1 = 10; - final int demand2 = 5; - final int totalDemand = demand1 + demand2; - - activePublisherTest(publisherElements, false, new PublisherTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - - sub.request(demand1); - sub.request(demand2); - - /* - NOTE: The order of the nextElement/cancel calls below is very important (!) - - If this ordering was reversed, given an asynchronous publisher, - the following scenario would be *legal* and would break this test: - - > AsyncPublisher receives request(10) - it does not emit data right away, it's asynchronous - > AsyncPublisher receives request(5) - demand is now 15 - ! AsyncPublisher didn't emit any onNext yet (!) - > AsyncPublisher receives cancel() - handles it right away, by "stopping itself" for example - ! cancel was handled hefore the AsyncPublisher ever got the chance to emit data - ! the subscriber ends up never receiving even one element - the test is stuck (and fails, even on valid Publisher) - - Which is why we must first expect an element, and then cancel, once the producing is "running". - */ - sub.nextElement(); - sub.cancel(); - - int onNextsSignalled = 1; - - boolean stillBeingSignalled; - do { - // put asyncError if onNext signal received - sub.expectNone(); - Throwable error = env.dropAsyncError(); - - if (error == null) { - stillBeingSignalled = false; - } else { - onNextsSignalled += 1; - stillBeingSignalled = true; - } - - // if the Publisher tries to emit more elements than was requested (and/or ignores cancellation) this will throw - assertTrue(onNextsSignalled <= totalDemand, - String.format("Publisher signalled [%d] elements, which is more than the signalled demand: %d", - onNextsSignalled, totalDemand)); - - } while (stillBeingSignalled); - } - }); - - env.verifyNoAsyncErrorsNoDelay(); - } - - @Override @Test - public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable { - final ReferenceQueue> queue = new ReferenceQueue>(); - - final Function, WeakReference>> run = new Function, WeakReference>>() { - @Override - public WeakReference> apply(Publisher pub) throws Exception { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final WeakReference> ref = new WeakReference>(sub, queue); - - sub.request(1); - sub.nextElement(); - sub.cancel(); - - return ref; - } - }; - - activePublisherTest(3, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final WeakReference> ref = run.apply(pub); - - // cancel may be run asynchronously so we add a sleep before running the GC - // to "resolve" the race - Thread.sleep(publisherReferenceGCTimeoutMillis); - System.gc(); - - if (!ref.equals(queue.remove(100))) { - env.flop(String.format("Publisher %s did not drop reference to test subscriber after subscription cancellation", pub)); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable { - final int totalElements = 3; - - activePublisherTest(totalElements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(Long.MAX_VALUE); - - sub.nextElements(totalElements); - sub.expectCompletion(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable { - final int totalElements = 3; - - activePublisherTest(totalElements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE / 2 - sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE - 1 - sub.request(1); // pending = Long.MAX_VALUE - - sub.nextElements(totalElements); - sub.expectCompletion(); - - try { - env.verifyNoAsyncErrorsNoDelay(); - } finally { - sub.cancel(); - } - - } - }); - } - - @Override @Test - public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable { - activePublisherTest(Integer.MAX_VALUE, false, new PublisherTestRun() { - @Override public void run(Publisher pub) throws Throwable { - final ManualSubscriberWithSubscriptionSupport sub = new BlackholeSubscriberWithSubscriptionSupport(env) { - // arbitrarily set limit on nuber of request calls signalled, we expect overflow after already 2 calls, - // so 10 is relatively high and safe even if arbitrarily chosen - int callsCounter = 10; - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (subscription.isCompleted()) { - if (callsCounter > 0) { - subscription.value().request(Long.MAX_VALUE - 1); - callsCounter--; - } else { - subscription.value().cancel(); - } - } else { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - }; - env.subscribe(pub, sub, env.defaultTimeoutMillis()); - - // eventually triggers `onNext`, which will then trigger up to `callsCounter` times `request(Long.MAX_VALUE - 1)` - // we're pretty sure to overflow from those - sub.request(1); - - // no onError should be signalled - try { - env.verifyNoAsyncErrors(); - } finally { - sub.cancel(); - } - } - }); - } - - ///////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - ///////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - public interface PublisherTestRun { - public void run(Publisher pub) throws Throwable; - } - - /** - * Test for feature that SHOULD/MUST be implemented, using a live publisher. - * - * @param elements the number of elements the Publisher under test must be able to emit to run this test - * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run. - * If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped. - * To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}. - */ - public void activePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun body) throws Throwable { - if (elements > maxElementsFromPublisher()) { - throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher())); - } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) { - throw new SkipException("Unable to run this test, as it requires an onComplete signal, " + - "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)"); - } else { - Publisher pub = createPublisher(elements); - body.run(pub); - env.verifyNoAsyncErrorsNoDelay(); - } - } - - /** - * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails. - * - * @param elements the number of elements the Publisher under test must be able to emit to run this test - * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run. - * If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped. - * To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}. - */ - public void optionalActivePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun body) throws Throwable { - if (elements > maxElementsFromPublisher()) { - throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher())); - } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) { - throw new SkipException("Unable to run this test, as it requires an onComplete signal, " + - "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)"); - } else { - - final Publisher pub = createPublisher(elements); - final String skipMessage = "Skipped because tested publisher does NOT implement this OPTIONAL requirement."; - - try { - potentiallyPendingTest(pub, body); - } catch (Exception ex) { - notVerified(skipMessage); - } catch (AssertionError ex) { - notVerified(skipMessage + " Reason for skipping was: " + ex.getMessage()); - } - } - } - - public static final String SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE = - "Skipping because no error state Publisher provided, and the test requires it. " + - "Please implement PublisherVerification#createFailedPublisher to run this test."; - - public static final String SKIPPING_OPTIONAL_TEST_FAILED = - "Skipping, because provided Publisher does not pass this *additional* verification."; - /** - * Additional test for Publisher in error state - */ - public void whenHasErrorPublisherTest(PublisherTestRun body) throws Throwable { - potentiallyPendingTest(createFailedPublisher(), body, SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE); - } - - public void potentiallyPendingTest(Publisher pub, PublisherTestRun body) throws Throwable { - potentiallyPendingTest(pub, body, SKIPPING_OPTIONAL_TEST_FAILED); - } - - public void potentiallyPendingTest(Publisher pub, PublisherTestRun body, String message) throws Throwable { - if (pub != null) { - body.run(pub); - } else { - throw new SkipException(message); - } - } - - /** - * Executes a given test body {@code n} times. - * All the test runs must pass in order for the stochastic test to pass. - */ - public void stochasticTest(int n, Function body) throws Throwable { - if (skipStochasticTests()) { - notVerified("Skipping @Stochastic test because `skipStochasticTests()` returned `true`!"); - } - - for (int i = 0; i < n; i++) { - body.apply(i); - } - } - - public void notVerified() { - throw new SkipException("Not verified by this TCK."); - } - - /** - * Return this value from {@link PublisherVerification#maxElementsFromPublisher()} to mark that the given {@link org.reactivestreams.Publisher}, - * is not able to signal completion. For example it is strictly a time-bound or unbounded source of data. - * - * Returning this value from {@link PublisherVerification#maxElementsFromPublisher()} will result in skipping all TCK tests which require onComplete signals! - */ - public long publisherUnableToSignalOnComplete() { - return Long.MAX_VALUE; - } - - public void notVerified(String message) { - throw new SkipException(message); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java deleted file mode 100644 index 62c899a7847..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.ManualPublisher; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules; -import org.reactivestreams.tck.flow.support.TestException; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.reactivestreams.tck.SubscriberWhiteboxVerification.BlackboxSubscriberProxy; -import static org.testng.Assert.assertTrue; - -/** - * Provides tests for verifying {@link org.reactivestreams.Subscriber} and {@link org.reactivestreams.Subscription} - * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing). - * - * This verification is NOT able to check many of the rules of the spec, and if you want more - * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification} - * instead. - * - * @see org.reactivestreams.Subscriber - * @see org.reactivestreams.Subscription - */ -public abstract class SubscriberBlackboxVerification extends WithHelperPublisher - implements SubscriberBlackboxVerificationRules { - - protected final TestEnvironment env; - - protected SubscriberBlackboxVerification(TestEnvironment env) { - this.env = env; - } - - // USER API - - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - */ - public abstract Subscriber createSubscriber(); - - /** - * Override this method if the Subscriber implementation you are verifying - * needs an external signal before it signals demand to its Publisher. - * - * By default this method does nothing. - */ - public void triggerRequest(final Subscriber subscriber) { - // this method is intentionally left blank - } - - // ENV SETUP - - /** - * Executor service used by the default provided asynchronous Publisher. - * @see #createHelperPublisher(long) - */ - private ExecutorService publisherExecutor; - @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); } - @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); } - @Override public ExecutorService publisherExecutorService() { return publisherExecutor; } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - @Override @Test - public void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws InterruptedException { - triggerRequest(stage.subProxy().sub()); - final long requested = stage.expectRequest();// assuming subscriber wants to consume elements... - final long signalsToEmit = Math.min(requested, 512); // protecting against Subscriber which sends ridiculous large demand - - // should cope with up to requested number of elements - for (int i = 0; i < signalsToEmit && sampleIsCancelled(stage, i, 10); i++) - stage.signalNext(); - - // we complete after `signalsToEmit` (which can be less than `requested`), - // which is legal under https://github.com/reactive-streams/reactive-streams-jvm#1.2 - stage.sendCompletion(); - } - - /** - * In order to allow some "skid" and not check state on each iteration, - * only check {@code stage.isCancelled} every {@code checkInterval}'th iteration. - */ - private boolean sampleIsCancelled(BlackboxTestStage stage, int i, int checkInterval) throws InterruptedException { - if (i % checkInterval == 0) return stage.isCancelled(); - else return false; - } - }); - } - - @Override @Test - public void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - final Optional onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackTraceElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackTraceElement.get(); - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - - @Override - public void cancel() { - final Optional onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackElement.get(); - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - }; - - final Subscriber sub = createSubscriber(); - sub.onSubscribe(subs); - sub.onComplete(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - - @Override - public void cancel() { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - }; - - final Subscriber sub = createSubscriber(); - sub.onSubscribe(subs); - sub.onError(new TestException()); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception { - new BlackboxTestStage(env) {{ - // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail - final TestEnvironment.Latch secondSubscriptionCancelled = new TestEnvironment.Latch(env); - sub().onSubscribe( - new Subscription() { - @Override - public void request(long elements) { - env.flop(String.format("Subscriber %s illegally called `subscription.request(%s)`!", sub(), elements)); - } - - @Override - public void cancel() { - secondSubscriptionCancelled.close(); - } - - @Override - public String toString() { - return "SecondSubscription(should get cancelled)"; - } - }); - - secondSubscriptionCancelled.expectClose("Expected SecondSubscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called."); - env.verifyNoAsyncErrorsNoDelay(); - sendCompletion(); // we're done, complete the subscriber under test - }}; - } - - @Override @Test - public void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - // the same thread part of the clause can be verified but that is not very useful, or is it? - } - - @Override @Test - public void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - triggerRequest(stage.subProxy().sub()); - final long notUsed = stage.expectRequest(); // received request signal - stage.sub().onComplete(); - stage.subProxy().expectCompletion(); - } - }); - } - - @Override @Test - public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - final Subscriber sub = stage.sub(); - sub.onComplete(); - stage.subProxy().expectCompletion(); - } - }); - } - - @Override @Test - public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - triggerRequest(stage.subProxy().sub()); - final long notUsed = stage.expectRequest(); // received request signal - stage.sub().onError(new TestException()); // in response to that, we fail - stage.subProxy().expectError(Throwable.class); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - - stage.sub().onError(new TestException()); - stage.subProxy().expectError(Throwable.class); - } - }); - } - - @Override @Test - public void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - try { - sub.onSubscribe(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subscription = new Subscription() { - @Override public void request(final long elements) {} - @Override public void cancel() {} - }; - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - sub.onSubscribe(subscription); - try { - sub.onNext(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onNext(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subscription = new Subscription() { - @Override public void request(final long elements) {} - @Override public void cancel() {} - }; - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - sub.onSubscribe(subscription); - try { - sub.onError(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onError(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION ////////////////// - - @Override @Test - public void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - /////////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - abstract class BlackboxTestStageTestRun { - public abstract void run(BlackboxTestStage stage) throws Throwable; - } - - public void blackboxSubscriberTest(BlackboxTestStageTestRun body) throws Throwable { - BlackboxTestStage stage = new BlackboxTestStage(env, true); - body.run(stage); - } - - public void blackboxSubscriberWithoutSetupTest(BlackboxTestStageTestRun body) throws Throwable { - BlackboxTestStage stage = new BlackboxTestStage(env, false); - body.run(stage); - } - - public class BlackboxTestStage extends ManualPublisher { - public Publisher pub; - public ManualSubscriber tees; // gives us access to an infinite stream of T values - - public T lastT = null; - private Optional> subProxy = Optional.empty(); - - public BlackboxTestStage(TestEnvironment env) throws InterruptedException { - this(env, true); - } - - public BlackboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException { - super(env); - if (runDefaultInit) { - pub = this.createHelperPublisher(Long.MAX_VALUE); - tees = env.newManualSubscriber(pub); - Subscriber sub = createSubscriber(); - subProxy = Optional.of(createBlackboxSubscriberProxy(env, sub)); - subscribe(subProxy.get()); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - /** - * Proxy for the {@link #sub()} {@code Subscriber}, providing certain assertions on methods being called on the Subscriber. - */ - public BlackboxSubscriberProxy subProxy() { - return subProxy.get(); - } - - public Publisher createHelperPublisher(long elements) { - return SubscriberBlackboxVerification.this.createHelperPublisher(elements); - } - - public BlackboxSubscriberProxy createBlackboxSubscriberProxy(TestEnvironment env, Subscriber sub) { - return new BlackboxSubscriberProxy(env, sub); - } - - public T signalNext() throws InterruptedException { - T element = nextT(); - sendNext(element); - return element; - } - - public T nextT() throws InterruptedException { - lastT = tees.requestNextElement(); - return lastT; - } - - } - - public void notVerified() { - throw new SkipException("Not verified using this TCK."); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java deleted file mode 100644 index f2304a11dc3..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (c) 2019, 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 org.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.*; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.TestException; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.testng.Assert.assertTrue; - -/** - * Provides whitebox style tests for verifying {@link org.reactivestreams.Subscriber} - * and {@link org.reactivestreams.Subscription} specification rules. - * - * @see org.reactivestreams.Subscriber - * @see org.reactivestreams.Subscription - */ -public abstract class SubscriberWhiteboxVerification extends WithHelperPublisher - implements SubscriberWhiteboxVerificationRules { - - private final TestEnvironment env; - - protected SubscriberWhiteboxVerification(TestEnvironment env) { - this.env = env; - } - - // USER API - - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - * - * In order to be meaningfully testable your Subscriber must inform the given - * `WhiteboxSubscriberProbe` of the respective events having been received. - */ - public abstract Subscriber createSubscriber(WhiteboxSubscriberProbe probe); - - // ENV SETUP - - /** - * Executor service used by the default provided asynchronous Publisher. - * @see #createHelperPublisher(long) - */ - private ExecutorService publisherExecutor; - @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); } - @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); } - @Override public ExecutorService publisherExecutorService() { return publisherExecutor; } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// TEST SETUP VERIFICATION ////////////////////////////// - - @Test - public void required_exerciseWhiteboxHappyPath() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - long receivedRequests = stage.expectRequest(); - - stage.signalNext(); - stage.probe.expectNext(stage.lastT); - - stage.puppet().triggerRequest(1); - if (receivedRequests == 1) { - stage.expectRequest(); - } - - stage.signalNext(); - stage.probe.expectNext(stage.lastT); - - stage.puppet().signalCancel(); - stage.expectCancelling(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.1 - @Override @Test - public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.expectRequest(); - - stage.signalNext(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.2 - @Override @Test - public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3 - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - subscriberTestWithoutSetup(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - final Optional onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackTraceElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackTraceElement.get(); - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - - @Override - public void cancel() { - final Optional onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackElement.get(); - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - }; - - stage.probe = stage.createWhiteboxSubscriberProbe(env); - final Subscriber sub = createSubscriber(stage.probe); - - sub.onSubscribe(subs); - sub.onComplete(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3 - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - subscriberTestWithoutSetup(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - - @Override - public void cancel() { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - }; - - stage.probe = stage.createWhiteboxSubscriberProbe(env); - final Subscriber sub = createSubscriber(stage.probe); - - sub.onSubscribe(subs); - sub.onError(new TestException()); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.4 - @Override @Test - public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.5 - @Override @Test - public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail - final Latch secondSubscriptionCancelled = new Latch(env); - final Subscriber sub = stage.sub(); - final Subscription subscription = new Subscription() { - @Override - public void request(long elements) { - // ignore... - } - - @Override - public void cancel() { - secondSubscriptionCancelled.close(); - } - - @Override - public String toString() { - return "SecondSubscription(should get cancelled)"; - } - }; - sub.onSubscribe(subscription); - - secondSubscriptionCancelled.expectClose("Expected 2nd Subscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called"); - env.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.6 - @Override @Test - public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.7 - @Override @Test - public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - // the same thread part of the clause can be verified but that is not very useful, or is it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.8 - @Override @Test - public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.expectRequest(); - stage.puppet().signalCancel(); - stage.expectCancelling(); - stage.signalNext(); - - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9 - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.sendCompletion(); - stage.probe.expectCompletion(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9 - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.sendCompletion(); - stage.probe.expectCompletion(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - Exception ex = new TestException(); - stage.sendError(ex); - stage.probe.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - Exception ex = new TestException(); - stage.sendError(ex); - stage.probe.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.11 - @Override @Test - public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.12 - @Override @Test - public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void untested_spec213_failingOnSignalInvocation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onSubscribe(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } - - assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException"); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onNext(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } - - assertTrue(gotNPE, "onNext(null) did not throw NullPointerException"); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onError(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } finally { - assertTrue(gotNPE, "onError(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - - ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION ////////////////// - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.1 - @Override @Test - public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.8 - @Override @Test - public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(2); - long requestedElements = stage.expectRequest(); - stage.probe.expectNext(stage.signalNext()); - // Some subscribers may only request one element at a time. - if (requestedElements < 2) { - stage.expectRequest(); - } - stage.probe.expectNext(stage.signalNext()); - - stage.probe.expectNone(); - stage.puppet().triggerRequest(3); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.10 - @Override @Test - public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.11 - @Override @Test - public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.14 - @Override @Test - public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.15 - @Override @Test - public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.16 - @Override @Test - public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - /////////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - abstract class TestStageTestRun { - public abstract void run(WhiteboxTestStage stage) throws Throwable; - } - - /** - * Prepares subscriber and publisher pair (by subscribing the first to the latter), - * and then hands over the tests {@link WhiteboxTestStage} over to the test. - * - * The test stage is, like in a puppet show, used to orchestrate what each participant should do. - * Since this is a whitebox test, this allows the stage to completely control when and how to signal / expect signals. - */ - public void subscriberTest(TestStageTestRun body) throws Throwable { - WhiteboxTestStage stage = new WhiteboxTestStage(env, true); - body.run(stage); - } - - /** - * Provides a {@link WhiteboxTestStage} without performing any additional setup, - * like the {@link #subscriberTest(SubscriberWhiteboxVerification.TestStageTestRun)} would. - * - * Use this method to write tests in which you need full control over when and how the initial {@code subscribe} is signalled. - */ - public void subscriberTestWithoutSetup(TestStageTestRun body) throws Throwable { - WhiteboxTestStage stage = new WhiteboxTestStage(env, false); - body.run(stage); - } - - /** - * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails. - */ - public void optionalSubscriberTestWithoutSetup(TestStageTestRun body) throws Throwable { - try { - subscriberTestWithoutSetup(body); - } catch (Exception ex) { - notVerified("Skipped because tested publisher does NOT implement this OPTIONAL requirement."); - } - } - - public class WhiteboxTestStage extends ManualPublisher { - public Publisher pub; - public ManualSubscriber tees; // gives us access to a stream T values - public WhiteboxSubscriberProbe probe; - - public T lastT = null; - - public WhiteboxTestStage(TestEnvironment env) throws InterruptedException { - this(env, true); - } - - public WhiteboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException { - super(env); - if (runDefaultInit) { - pub = this.createHelperPublisher(Long.MAX_VALUE); - tees = env.newManualSubscriber(pub); - probe = new WhiteboxSubscriberProbe(env, subscriber); - subscribe(createSubscriber(probe)); - probe.puppet.expectCompletion(env.defaultTimeoutMillis(), String.format("Subscriber %s did not `registerOnSubscribe`", sub())); - env.verifyNoAsyncErrorsNoDelay(); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - public SubscriberPuppet puppet() { - return probe.puppet(); - } - - public WhiteboxSubscriberProbe probe() { - return probe; - } - - public Publisher createHelperPublisher(long elements) { - return SubscriberWhiteboxVerification.this.createHelperPublisher(elements); - } - - public WhiteboxSubscriberProbe createWhiteboxSubscriberProbe(TestEnvironment env) { - return new WhiteboxSubscriberProbe(env, subscriber); - } - - public T signalNext() throws InterruptedException { - return signalNext(nextT()); - } - - private T signalNext(T element) throws InterruptedException { - sendNext(element); - return element; - } - - public T nextT() throws InterruptedException { - lastT = tees.requestNextElement(); - return lastT; - } - - public void verifyNoAsyncErrors() { - env.verifyNoAsyncErrors(); - } - } - - /** - * This class is intented to be used as {@code Subscriber} decorator and should be used in {@code pub.subscriber(...)} calls, - * in order to allow intercepting calls on the underlying {@code Subscriber}. - * This delegation allows the proxy to implement {@link BlackboxProbe} assertions. - */ - public static class BlackboxSubscriberProxy extends BlackboxProbe implements Subscriber { - - public BlackboxSubscriberProxy(TestEnvironment env, Subscriber subscriber) { - super(env, Promise.>completed(env, subscriber)); - } - - @Override - public void onSubscribe(Subscription s) { - sub().onSubscribe(s); - } - - @Override - public void onNext(T t) { - registerOnNext(t); - sub().onNext(t); - } - - @Override - public void onError(Throwable cause) { - registerOnError(cause); - sub().onError(cause); - } - - @Override - public void onComplete() { - registerOnComplete(); - sub().onComplete(); - } - } - - public static class BlackboxProbe implements SubscriberProbe { - protected final TestEnvironment env; - protected final Promise> subscriber; - - protected final Receptacle elements; - protected final Promise error; - - public BlackboxProbe(TestEnvironment env, Promise> subscriber) { - this.env = env; - this.subscriber = subscriber; - elements = new Receptacle(env); - error = new Promise(env); - } - - @Override - public void registerOnNext(T element) { - elements.add(element); - } - - @Override - public void registerOnComplete() { - try { - elements.complete(); - } catch (IllegalStateException ex) { - // "Queue full", onComplete was already called - env.flop("subscriber::onComplete was called a second time, which is illegal according to Rule 1.7"); - } - } - - @Override - public void registerOnError(Throwable cause) { - try { - error.complete(cause); - } catch (IllegalStateException ex) { - // "Queue full", onError was already called - env.flop("subscriber::onError was called a second time, which is illegal according to Rule 1.7"); - } - } - - public T expectNext() throws InterruptedException { - return elements.next(env.defaultTimeoutMillis(), String.format("Subscriber %s did not call `registerOnNext(_)`", sub())); - } - - public void expectNext(T expected) throws InterruptedException { - expectNext(expected, env.defaultTimeoutMillis()); - } - - public void expectNext(T expected, long timeoutMillis) throws InterruptedException { - T received = elements.next(timeoutMillis, String.format("Subscriber %s did not call `registerOnNext(%s)`", sub(), expected)); - if (!received.equals(expected)) { - env.flop(String.format("Subscriber %s called `registerOnNext(%s)` rather than `registerOnNext(%s)`", sub(), received, expected)); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - public void expectCompletion() throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis()); - } - - public void expectCompletion(long timeoutMillis) throws InterruptedException { - expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnComplete()`", sub())); - } - - public void expectCompletion(long timeoutMillis, String msg) throws InterruptedException { - elements.expectCompletion(timeoutMillis, msg); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectErrorWithMessage(Class expected, String requiredMessagePart) throws InterruptedException { - final E err = expectError(expected); - String message = err.getMessage(); - assertTrue(message.contains(requiredMessagePart), - String.format("Got expected exception %s but missing message [%s], was: %s", err.getClass(), requiredMessagePart, expected)); - } - - public E expectError(Class expected) throws InterruptedException { - return expectError(expected, env.defaultTimeoutMillis()); - } - - @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - public E expectError(Class expected, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - if (error.value() == null) { - return env.flopAndFail(String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - } else if (expected.isInstance(error.value())) { - return (E) error.value(); - } else { - return env.flopAndFail(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected)); - } - } - - public void expectError(Throwable expected) throws InterruptedException { - expectError(expected, env.defaultTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectError(Throwable expected, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - if (error.value() != expected) { - env.flop(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected)); - } - } - - public void expectNone() throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis()); - } - - public void expectNone(long withinMillis) throws InterruptedException { - elements.expectNone(withinMillis, "Expected nothing"); - } - - } - - public static class WhiteboxSubscriberProbe extends BlackboxProbe implements SubscriberPuppeteer { - protected Promise puppet; - - public WhiteboxSubscriberProbe(TestEnvironment env, Promise> subscriber) { - super(env, subscriber); - puppet = new Promise(env); - } - - private SubscriberPuppet puppet() { - return puppet.value(); - } - - @Override - public void registerOnSubscribe(SubscriberPuppet p) { - if (!puppet.isCompleted()) { - puppet.complete(p); - } - } - - } - - public interface SubscriberPuppeteer { - - /** - * Must be called by the test subscriber when it has successfully registered a subscription - * inside the `onSubscribe` method. - */ - void registerOnSubscribe(SubscriberPuppet puppet); - } - - public interface SubscriberProbe { - - /** - * Must be called by the test subscriber when it has received an`onNext` event. - */ - void registerOnNext(T element); - - /** - * Must be called by the test subscriber when it has received an `onComplete` event. - */ - void registerOnComplete(); - - /** - * Must be called by the test subscriber when it has received an `onError` event. - */ - void registerOnError(Throwable cause); - - } - - /** - * Implement this puppet in your Whitebox style tests. - * The test suite will invoke the specific trigger/signal methods requesting you to execute the specific action. - * Since this is a whitebox style test, you're allowed and expected to use knowladge about your implementation to - * make implement these calls. - */ - public interface SubscriberPuppet { - - /** - * Ensure that at least {@code elements} are eventually requested by your {@link Subscriber}, if it hasn't already - * requested that many elements. - *

    - * This does not necessarily have to correlate 1:1 with a {@code Subscription.request(elements)} call, but the sum - * of the elements requested by your {@code Subscriber} must eventually be at least the sum of the elements - * triggered to be requested by all the invocations of this method. - *

    - * Additionally, subscribers are permitted to delay requesting elements until previous requests for elements have - * been fulfilled. For example, a subscriber that only requests one element at a time may fulfill the request made - * by this method by requesting one element {@code elements} times, waiting for each element to arrive before the - * next request is made. - *

    - * Before sending any element to the subscriber, the TCK must wait for the subscriber to request that element, and - * must be prepared for the subscriber to only request one element at a time, it is not enough for the TCK to - * simply invoke this method before sending elements. - *

    - * An invocation of {@link #signalCancel()} may be coalesced into any elements that have not yet been requested, - * such that only a cancel signal is emitted. - */ - void triggerRequest(long elements); - - /** - * Trigger {@code cancel()} on your {@link Subscriber}. - *

    - * An invocation of this method may be coalesced into any outstanding requests, as requested by - *{@link #triggerRequest(long)}, such that only a cancel signal is emitted. - */ - void signalCancel(); - } - - public void notVerified() { - throw new SkipException("Not verified using this TCK."); - } - - public void notVerified(String msg) { - throw new SkipException(msg); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java deleted file mode 100644 index e32b58cbd13..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberBufferOverflowException; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class TestEnvironment { - public static final int TEST_BUFFER_SIZE = 16; - - private static final String DEFAULT_TIMEOUT_MILLIS_ENV = "DEFAULT_TIMEOUT_MILLIS"; - private static final long DEFAULT_TIMEOUT_MILLIS = 100; - - private static final String DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV = "DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS"; - private static final String DEFAULT_POLL_TIMEOUT_MILLIS_ENV = "DEFAULT_POLL_TIMEOUT_MILLIS_ENV"; - - private final long defaultTimeoutMillis; - private final long defaultPollTimeoutMillis; - private final long defaultNoSignalsTimeoutMillis; - private final boolean printlnDebug; - - private CopyOnWriteArrayList asyncErrors = new CopyOnWriteArrayList(); - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't - * preempted by an asynchronous event. - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis, - boolean printlnDebug) { - this.defaultTimeoutMillis = defaultTimeoutMillis; - this.defaultPollTimeoutMillis = defaultPollTimeoutMillis; - this.defaultNoSignalsTimeoutMillis = defaultNoSignalsTimeoutMillis; - this.printlnDebug = printlnDebug; - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, boolean printlnDebug) { - this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultTimeoutMillis, printlnDebug); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't - * preempted by an asynchronous event. - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis) { - this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultPollTimeoutMillis, false); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis) { - this(defaultTimeoutMillis, defaultTimeoutMillis, defaultNoSignalsTimeoutMillis); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - */ - public TestEnvironment(long defaultTimeoutMillis) { - this(defaultTimeoutMillis, defaultTimeoutMillis, defaultTimeoutMillis); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS} - * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used. - * - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - * often helpful to pinpoint simple race conditions etc. - */ - public TestEnvironment(boolean printlnDebug) { - this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis(), envDefaultPollTimeoutMillis(), printlnDebug); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS} - * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used. - */ - public TestEnvironment() { - this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis()); - } - - /** This timeout is used when waiting for a signal to arrive. */ - public long defaultTimeoutMillis() { - return defaultTimeoutMillis; - } - - /** - * This timeout is used when asserting that no further signals are emitted. - * Note that this timeout default - */ - public long defaultNoSignalsTimeoutMillis() { - return defaultNoSignalsTimeoutMillis; - } - - /** - * The default amount of time to poll for events if {@code defaultTimeoutMillis} isn't preempted by an asynchronous - * event. - */ - public long defaultPollTimeoutMillis() { - return defaultPollTimeoutMillis; - } - - /** - * Tries to parse the env variable {@code DEFAULT_TIMEOUT_MILLIS} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return DEFAULT_TIMEOUT_MILLIS; - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * Tries to parse the env variable {@code DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultNoSignalsTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return envDefaultTimeoutMillis(); - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * Tries to parse the env variable {@code DEFAULT_POLL_TIMEOUT_MILLIS_ENV} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultPollTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_POLL_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return envDefaultTimeoutMillis(); - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_POLL_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(String msg) { - try { - fail(msg); - } catch (Throwable t) { - asyncErrors.add(t); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(Throwable thr, String msg) { - try { - fail(msg, thr); - } catch (Throwable t) { - asyncErrors.add(thr); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(Throwable thr) { - try { - fail(thr.getMessage(), thr); - } catch (Throwable t) { - asyncErrors.add(thr); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * - * This method DOES fail the test right away (it tries to, by throwing an AssertionException), - * in such it is different from {@link org.reactivestreams.tck.TestEnvironment#flop} which only records the error. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public T flopAndFail(String msg) { - try { - fail(msg); - } catch (Throwable t) { - asyncErrors.add(t); - fail(msg, t); - } - return null; // unreachable, the previous block will always exit by throwing - } - - - - public void subscribe(Publisher pub, TestSubscriber sub) throws InterruptedException { - subscribe(pub, sub, defaultTimeoutMillis); - } - - public void subscribe(Publisher pub, TestSubscriber sub, long timeoutMillis) throws InterruptedException { - pub.subscribe(sub); - sub.subscription.expectCompletion(timeoutMillis, String.format("Could not subscribe %s to Publisher %s", sub, pub)); - verifyNoAsyncErrorsNoDelay(); - } - - public ManualSubscriber newBlackholeSubscriber(Publisher pub) throws InterruptedException { - ManualSubscriberWithSubscriptionSupport sub = new BlackholeSubscriberWithSubscriptionSupport(this); - subscribe(pub, sub, defaultTimeoutMillis()); - return sub; - } - - public ManualSubscriber newManualSubscriber(Publisher pub) throws InterruptedException { - return newManualSubscriber(pub, defaultTimeoutMillis()); - } - - public ManualSubscriber newManualSubscriber(Publisher pub, long timeoutMillis) throws InterruptedException { - ManualSubscriberWithSubscriptionSupport sub = new ManualSubscriberWithSubscriptionSupport(this); - subscribe(pub, sub, timeoutMillis); - return sub; - } - - public void clearAsyncErrors() { - asyncErrors.clear(); - } - - public Throwable dropAsyncError() { - try { - return asyncErrors.remove(0); - } catch (IndexOutOfBoundsException ex) { - return null; - } - } - - /** - * Waits for {@link TestEnvironment#defaultNoSignalsTimeoutMillis()} and then verifies that no asynchronous errors - * were signalled pior to, or during that time (by calling {@code flop()}). - */ - public void verifyNoAsyncErrors() { - verifyNoAsyncErrors(defaultNoSignalsTimeoutMillis()); - } - - /** - * This version of {@code verifyNoAsyncErrors} should be used when errors still could be signalled - * asynchronously during {@link TestEnvironment#defaultTimeoutMillis()} time. - *

    - * It will immediatly check if any async errors were signaled (using {@link TestEnvironment#flop(String)}, - * and if no errors encountered wait for another default timeout as the errors may yet be signalled. - * The initial check is performed in order to fail-fast in case of an already failed test. - */ - public void verifyNoAsyncErrors(long delay) { - try { - verifyNoAsyncErrorsNoDelay(); - - Thread.sleep(delay); - verifyNoAsyncErrorsNoDelay(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - /** - * Verifies that no asynchronous errors were signalled pior to calling this method (by calling {@code flop()}). - * This version of verifyNoAsyncError does not wait before checking for asynchronous errors, and is to be used - * for example in tight loops etc. - */ - public void verifyNoAsyncErrorsNoDelay() { - for (Throwable e : asyncErrors) { - if (e instanceof AssertionError) { - throw (AssertionError) e; - } else { - fail(String.format("Async error during test execution: %s", e.getMessage()), e); - } - } - } - - /** If {@code TestEnvironment#printlnDebug} is true, print debug message to std out. */ - public void debug(String msg) { - if (debugEnabled()) { - System.out.printf("[TCK-DEBUG] %s%n", msg); - } - } - - public final boolean debugEnabled() { - return printlnDebug; - } - - /** - * Looks for given {@code method} method in stack trace. - * Can be used to answer questions like "was this method called from onComplete?". - * - * @return the caller's StackTraceElement at which he the looked for method was found in the call stack, EMPTY otherwise - */ - public Optional findCallerMethodInStackTrace(String method) { - final Throwable thr = new Throwable(); // gets the stacktrace - - for (StackTraceElement stackElement : thr.getStackTrace()) { - if (stackElement.getMethodName().equals(method)) { - return Optional.of(stackElement); - } - } - return Optional.empty(); - } - - // ---- classes ---- - - /** - * {@link Subscriber} implementation which can be steered by test code and asserted on. - */ - public static class ManualSubscriber extends TestSubscriber { - Receptacle received; - - public ManualSubscriber(TestEnvironment env) { - super(env); - received = new Receptacle(this.env); - } - - @Override - public void onNext(T element) { - try { - received.add(element); - } catch (IllegalStateException ex) { - // error message refinement - throw new SubscriberBufferOverflowException( - String.format("Received more than bufferSize (%d) onNext signals. " + - "The Publisher probably emited more signals than expected!", - received.QUEUE_SIZE), ex); - } - } - - @Override - public void onComplete() { - received.complete(); - } - - public void request(long elements) { - subscription.value().request(elements); - } - - public T requestNextElement() throws InterruptedException { - return requestNextElement(env.defaultTimeoutMillis()); - } - - public T requestNextElement(long timeoutMillis) throws InterruptedException { - return requestNextElement(timeoutMillis, "Did not receive expected element"); - } - - public T requestNextElement(String errorMsg) throws InterruptedException { - return requestNextElement(env.defaultTimeoutMillis(), errorMsg); - } - - public T requestNextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - return nextElement(timeoutMillis, errorMsg); - } - - public Optional requestNextElementOrEndOfStream() throws InterruptedException { - return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public Optional requestNextElementOrEndOfStream(String errorMsg) throws InterruptedException { - return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), errorMsg); - } - - public Optional requestNextElementOrEndOfStream(long timeoutMillis) throws InterruptedException { - return requestNextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public Optional requestNextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - return nextElementOrEndOfStream(timeoutMillis, errorMsg); - } - - public void requestEndOfStream() throws InterruptedException { - requestEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public void requestEndOfStream(long timeoutMillis) throws InterruptedException { - requestEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public void requestEndOfStream(String errorMsg) throws InterruptedException { - requestEndOfStream(env.defaultTimeoutMillis(), errorMsg); - } - - public void requestEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - expectCompletion(timeoutMillis, errorMsg); - } - - public List requestNextElements(long elements) throws InterruptedException { - request(elements); - return nextElements(elements, env.defaultTimeoutMillis()); - } - - public List requestNextElements(long elements, long timeoutMillis) throws InterruptedException { - request(elements); - return nextElements(elements, timeoutMillis, String.format("Did not receive %d expected elements", elements)); - } - - public List requestNextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - request(elements); - return nextElements(elements, timeoutMillis, errorMsg); - } - - public T nextElement() throws InterruptedException { - return nextElement(env.defaultTimeoutMillis()); - } - - public T nextElement(long timeoutMillis) throws InterruptedException { - return nextElement(timeoutMillis, "Did not receive expected element"); - } - - public T nextElement(String errorMsg) throws InterruptedException { - return nextElement(env.defaultTimeoutMillis(), errorMsg); - } - - public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - return received.next(timeoutMillis, errorMsg); - } - - public Optional nextElementOrEndOfStream() throws InterruptedException { - return nextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public Optional nextElementOrEndOfStream(long timeoutMillis) throws InterruptedException { - return nextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public Optional nextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - return received.nextOrEndOfStream(timeoutMillis, errorMsg); - } - - public List nextElements(long elements) throws InterruptedException { - return nextElements(elements, env.defaultTimeoutMillis(), "Did not receive expected element or completion"); - } - - public List nextElements(long elements, String errorMsg) throws InterruptedException { - return nextElements(elements, env.defaultTimeoutMillis(), errorMsg); - } - - public List nextElements(long elements, long timeoutMillis) throws InterruptedException { - return nextElements(elements, timeoutMillis, "Did not receive expected element or completion"); - } - - public List nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - return received.nextN(elements, timeoutMillis, errorMsg); - } - - public void expectNext(T expected) throws InterruptedException { - expectNext(expected, env.defaultTimeoutMillis()); - } - - public void expectNext(T expected, long timeoutMillis) throws InterruptedException { - T received = nextElement(timeoutMillis, "Did not receive expected element on downstream"); - if (!received.equals(expected)) { - env.flop(String.format("Expected element %s on downstream but received %s", expected, received)); - } - } - - public void expectCompletion() throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public void expectCompletion(long timeoutMillis) throws InterruptedException { - expectCompletion(timeoutMillis, "Did not receive expected stream completion"); - } - - public void expectCompletion(String errorMsg) throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis(), errorMsg); - } - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - received.expectCompletion(timeoutMillis, errorMsg); - } - - public void expectErrorWithMessage(Class expected, String requiredMessagePart) throws Exception { - expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis()); - } - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives) throws Exception { - expectErrorWithMessage(expected, requiredMessagePartAlternatives, env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectErrorWithMessage(Class expected, String requiredMessagePart, long timeoutMillis) throws Exception { - expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), timeoutMillis); - } - - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives, long timeoutMillis) throws Exception { - expectErrorWithMessage(expected, requiredMessagePartAlternatives, timeoutMillis, timeoutMillis); - } - - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives, - long totalTimeoutMillis, long pollTimeoutMillis) throws Exception { - final E err = expectError(expected, totalTimeoutMillis, pollTimeoutMillis); - final String message = err.getMessage(); - - boolean contains = false; - for (String requiredMessagePart : requiredMessagePartAlternatives) - if (message.contains(requiredMessagePart)) contains = true; // not short-circuting loop, it is expected to - assertTrue(contains, - String.format("Got expected exception [%s] but missing message part [%s], was: %s", - err.getClass(), "anyOf: " + requiredMessagePartAlternatives, err.getMessage())); - } - - public E expectError(Class expected) throws Exception { - return expectError(expected, env.defaultTimeoutMillis()); - } - - public E expectError(Class expected, long timeoutMillis) throws Exception { - return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis()); - } - - public E expectError(Class expected, String errorMsg) throws Exception { - return expectError(expected, env.defaultTimeoutMillis(), errorMsg); - } - - public E expectError(Class expected, long timeoutMillis, String errorMsg) throws Exception { - return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis(), errorMsg); - } - - public E expectError(Class expected, long totalTimeoutMillis, long pollTimeoutMillis) throws Exception { - return expectError(expected, totalTimeoutMillis, pollTimeoutMillis, String.format("Expected onError(%s)", expected.getName())); - } - - public E expectError(Class expected, long totalTimeoutMillis, long pollTimeoutMillis, - String errorMsg) throws Exception { - return received.expectError(expected, totalTimeoutMillis, pollTimeoutMillis, errorMsg); - } - - public void expectNone() throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis()); - } - - public void expectNone(String errMsgPrefix) throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis(), errMsgPrefix); - } - - public void expectNone(long withinMillis) throws InterruptedException { - expectNone(withinMillis, "Did not expect an element but got element"); - } - - public void expectNone(long withinMillis, String errMsgPrefix) throws InterruptedException { - received.expectNone(withinMillis, errMsgPrefix); - } - - } - - public static class ManualSubscriberWithSubscriptionSupport extends ManualSubscriber { - - public ManualSubscriberWithSubscriptionSupport(TestEnvironment env) { - super(env); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (subscription.isCompleted()) { - super.onNext(element); - } else { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - - @Override - public void onComplete() { - if (env.debugEnabled()) { - env.debug(this + "::onComplete()"); - } - if (subscription.isCompleted()) { - super.onComplete(); - } else { - env.flop("Subscriber::onComplete() called before Subscriber::onSubscribe"); - } - } - - @Override - public void onSubscribe(Subscription s) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onSubscribe(%s)", this, s)); - } - if (!subscription.isCompleted()) { - subscription.complete(s); - } else { - env.flop("Subscriber::onSubscribe called on an already-subscribed Subscriber"); - } - } - - @Override - public void onError(Throwable cause) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onError(%s)", this, cause)); - } - if (subscription.isCompleted()) { - super.onError(cause); - } else { - env.flop(cause, String.format("Subscriber::onError(%s) called before Subscriber::onSubscribe", cause)); - } - } - } - - /** - * Similar to {@link org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport} - * but does not accumulate values signalled via onNext, thus it can not be used to assert - * values signalled to this subscriber. Instead it may be used to quickly drain a given publisher. - */ - public static class BlackholeSubscriberWithSubscriptionSupport - extends ManualSubscriberWithSubscriptionSupport { - - public BlackholeSubscriberWithSubscriptionSupport(TestEnvironment env) { - super(env); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (!subscription.isCompleted()) { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - - @Override - public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!"); - } - - @Override - public List nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!"); - } - } - - public static class TestSubscriber implements Subscriber { - final Promise subscription; - - protected final TestEnvironment env; - - public TestSubscriber(TestEnvironment env) { - this.env = env; - subscription = new Promise(env); - } - - @Override - public void onError(Throwable cause) { - env.flop(cause, String.format("Unexpected Subscriber::onError(%s)", cause)); - } - - @Override - public void onComplete() { - env.flop("Unexpected Subscriber::onComplete()"); - } - - @Override - public void onNext(T element) { - env.flop(String.format("Unexpected Subscriber::onNext(%s)", element)); - } - - @Override - public void onSubscribe(Subscription subscription) { - env.flop(String.format("Unexpected Subscriber::onSubscribe(%s)", subscription)); - } - - public void cancel() { - if (subscription.isCompleted()) { - subscription.value().cancel(); - } else { - env.flop("Cannot cancel a subscription before having received it"); - } - } - } - - public static class ManualPublisher implements Publisher { - protected final TestEnvironment env; - - protected long pendingDemand = 0L; - protected Promise> subscriber; - - protected final Receptacle requests; - - protected final Latch cancelled; - - public ManualPublisher(TestEnvironment env) { - this.env = env; - requests = new Receptacle(env); - cancelled = new Latch(env); - subscriber = new Promise>(this.env); - } - - @Override - public void subscribe(Subscriber s) { - if (!subscriber.isCompleted()) { - subscriber.completeImmediatly(s); - - Subscription subs = new Subscription() { - @Override - public void request(long elements) { - requests.add(elements); - } - - @Override - public void cancel() { - cancelled.close(); - } - }; - s.onSubscribe(subs); - - } else { - env.flop("TestPublisher doesn't support more than one Subscriber"); - } - } - - public void sendNext(T element) { - if (subscriber.isCompleted()) { - subscriber.value().onNext(element); - } else { - env.flop("Cannot sendNext before having a Subscriber"); - } - } - - public void sendCompletion() { - if (subscriber.isCompleted()) { - subscriber.value().onComplete(); - } else { - env.flop("Cannot sendCompletion before having a Subscriber"); - } - } - - public void sendError(Throwable cause) { - if (subscriber.isCompleted()) { - subscriber.value().onError(cause); - } else { - env.flop("Cannot sendError before having a Subscriber"); - } - } - - public long expectRequest() throws InterruptedException { - return expectRequest(env.defaultTimeoutMillis()); - } - - public long expectRequest(long timeoutMillis) throws InterruptedException { - long requested = requests.next(timeoutMillis, "Did not receive expected `request` call"); - if (requested <= 0) { - return env.flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested)); - } else { - pendingDemand += requested; - return requested; - } - } - - - public long expectRequest(long timeoutMillis, String errorMessageAddendum) throws InterruptedException { - long requested = requests.next(timeoutMillis, String.format("Did not receive expected `request` call. %s", errorMessageAddendum)); - if (requested <= 0) { - return env.flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested)); - } else { - pendingDemand += requested; - return requested; - } - } - - public void expectExactRequest(long expected) throws InterruptedException { - expectExactRequest(expected, env.defaultTimeoutMillis()); - } - - public void expectExactRequest(long expected, long timeoutMillis) throws InterruptedException { - long requested = expectRequest(timeoutMillis); - if (requested != expected) { - env.flop(String.format("Received `request(%d)` on upstream but expected `request(%d)`", requested, expected)); - } - pendingDemand += requested; - } - - public void expectNoRequest() throws InterruptedException { - expectNoRequest(env.defaultTimeoutMillis()); - } - - public void expectNoRequest(long timeoutMillis) throws InterruptedException { - requests.expectNone(timeoutMillis, "Received an unexpected call to: request: "); - } - - public void expectCancelling() throws InterruptedException { - expectCancelling(env.defaultTimeoutMillis()); - } - - public void expectCancelling(long timeoutMillis) throws InterruptedException { - cancelled.expectClose(timeoutMillis, "Did not receive expected cancelling of upstream subscription"); - } - - public boolean isCancelled() throws InterruptedException { - return cancelled.isClosed(); - } - } - - /** - * Like a CountDownLatch, but resettable and with some convenience methods - */ - public static class Latch { - private final TestEnvironment env; - volatile private CountDownLatch countDownLatch = new CountDownLatch(1); - - public Latch(TestEnvironment env) { - this.env = env; - } - - public void reOpen() { - countDownLatch = new CountDownLatch(1); - } - - public boolean isClosed() { - return countDownLatch.getCount() == 0; - } - - public void close() { - countDownLatch.countDown(); - } - - public void assertClosed(String openErrorMsg) { - if (!isClosed()) { - env.flop(new ExpectedClosedLatchException(openErrorMsg)); - } - } - - public void assertOpen(String closedErrorMsg) { - if (isClosed()) { - env.flop(new ExpectedOpenLatchException(closedErrorMsg)); - } - } - - public void expectClose(String notClosedErrorMsg) throws InterruptedException { - expectClose(env.defaultTimeoutMillis(), notClosedErrorMsg); - } - - public void expectClose(long timeoutMillis, String notClosedErrorMsg) throws InterruptedException { - countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS); - if (countDownLatch.getCount() > 0) { - env.flop(String.format("%s within %d ms", notClosedErrorMsg, timeoutMillis)); - } - } - - static final class ExpectedOpenLatchException extends RuntimeException { - public ExpectedOpenLatchException(String message) { - super(message); - } - } - - static final class ExpectedClosedLatchException extends RuntimeException { - public ExpectedClosedLatchException(String message) { - super(message); - } - } - - } - - // simple promise for *one* value, which cannot be reset - public static class Promise { - private final TestEnvironment env; - - public static Promise completed(TestEnvironment env, T value) { - Promise promise = new Promise(env); - promise.completeImmediatly(value); - return promise; - } - - public Promise(TestEnvironment env) { - this.env = env; - } - - private ArrayBlockingQueue abq = new ArrayBlockingQueue(1); - private AtomicReference _value = new AtomicReference(); - - public T value() { - final T value = _value.get(); - if (value != null) { - return value; - } else { - env.flop("Cannot access promise value before completion"); - return null; - } - } - - public boolean isCompleted() { - return _value.get() != null; - } - - /** - * Allows using expectCompletion to await for completion of the value and complete it _then_ - */ - public void complete(T value) { - if (_value.compareAndSet(null, value)) { - // we add the value to the queue such to wake up any expectCompletion which was triggered before complete() was called - abq.add(value); - } else { - env.flop(String.format("Cannot complete a promise more than once! Present value: %s, attempted to set: %s", _value.get(), value)); - } - } - - /** - * Same as complete. - * - * Keeping this method for binary compatibility. - */ - public void completeImmediatly(T value) { - complete(value); - } - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - if (!isCompleted()) { - T val = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (val == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } - } - } - } - - // a "Promise" for multiple values, which also supports "end-of-stream reached" - public static class Receptacle { - final int QUEUE_SIZE = 2 * TEST_BUFFER_SIZE; - private final TestEnvironment env; - - private final ArrayBlockingQueue> abq = new ArrayBlockingQueue>(QUEUE_SIZE); - - private final Latch completedLatch; - - Receptacle(TestEnvironment env) { - this.env = env; - this.completedLatch = new Latch(env); - } - - public void add(T value) { - completedLatch.assertOpen(String.format("Unexpected element %s received after stream completed", value)); - - abq.add(Optional.of(value)); - } - - public void complete() { - completedLatch.assertOpen("Unexpected additional complete signal received!"); - completedLatch.close(); - - abq.add(Optional.empty()); - } - - public T next(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - return env.flopAndFail(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } else if (value.isDefined()) { - return value.get(); - } else { - return env.flopAndFail("Expected element but got end-of-stream"); - } - } - - public Optional nextOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - return Optional.empty(); - } - - return value; - } - - /** - * @param timeoutMillis total timeout time for awaiting all {@code elements} number of elements - */ - public List nextN(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - List result = new LinkedList(); - long remaining = elements; - long deadline = System.currentTimeMillis() + timeoutMillis; - while (remaining > 0) { - long remainingMillis = deadline - System.currentTimeMillis(); - - result.add(next(remainingMillis, errorMsg)); - remaining--; - } - - return result; - } - - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } else if (value.isDefined()) { - env.flop(String.format("Expected end-of-stream but got element [%s]", value.get())); - } // else, ok - } - - /** - * @deprecated Deprecated in favor of {@link #expectError(Class, long, long, String)}. - */ - @Deprecated - public E expectError(Class clazz, long timeoutMillis, String errorMsg) throws Exception { - return expectError(clazz, timeoutMillis, timeoutMillis, errorMsg); - } - - @SuppressWarnings("unchecked") - final E expectError(Class clazz, final long totalTimeoutMillis, - long pollTimeoutMillis, - String errorMsg) throws Exception { - long totalTimeoutRemainingNs = MILLISECONDS.toNanos(totalTimeoutMillis); - long timeStampANs = System.nanoTime(); - long timeStampBNs; - - for (;;) { - Thread.sleep(Math.min(pollTimeoutMillis, NANOSECONDS.toMillis(totalTimeoutRemainingNs))); - - if (env.asyncErrors.isEmpty()) { - timeStampBNs = System.nanoTime(); - totalTimeoutRemainingNs =- timeStampBNs - timeStampANs; - timeStampANs = timeStampBNs; - - if (totalTimeoutRemainingNs <= 0) { - return env.flopAndFail(String.format("%s within %d ms", errorMsg, totalTimeoutMillis)); - } - } else { - // ok, there was an expected error - Throwable thrown = env.asyncErrors.remove(0); - - if (clazz.isInstance(thrown)) { - return (E) thrown; - } else { - - return env.flopAndFail(String.format("%s within %d ms; Got %s but expected %s", - errorMsg, totalTimeoutMillis, thrown.getClass().getCanonicalName(), clazz.getCanonicalName())); - } - } - } - } - - public void expectNone(long withinMillis, String errorMsgPrefix) throws InterruptedException { - Thread.sleep(withinMillis); - Optional value = abq.poll(); - - if (value == null) { - // ok - } else if (value.isDefined()) { - env.flop(String.format("%s [%s]", errorMsgPrefix, value.get())); - } else { - env.flop("Expected no element but got end-of-stream"); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java deleted file mode 100644 index 2441a87f20c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.HelperPublisher; -import org.reactivestreams.tck.flow.support.InfiniteHelperPublisher; - -import java.util.concurrent.ExecutorService; - -/** - * Type which is able to create elements based on a seed {@code id} value. - *

    - * Simplest implementations will simply return the incoming id as the element. - * - * @param type of element to be delivered to the Subscriber - */ -public abstract class WithHelperPublisher { - - /** ExecutorService to be used by the provided helper {@link org.reactivestreams.Publisher} */ - public abstract ExecutorService publisherExecutorService(); - - /** - * Implement this method to match your expected element type. - * In case of implementing a simple Subscriber which is able to consume any kind of element simply return the - * incoming {@code element} element. - *

    - * Sometimes the Subscriber may be limited in what type of element it is able to consume, this you may have to implement - * this method such that the emitted element matches the Subscribers requirements. Simplest implementations would be - * to simply pass in the {@code element} as payload of your custom element, such as appending it to a String or other identifier. - *

    - * Warning: This method may be called concurrently by the helper publisher, thus it should be implemented in a - * thread-safe manner. - * - * @return element of the matching type {@code T} that will be delivered to the tested Subscriber - */ - public abstract T createElement(int element); - - /** - * Helper method required for creating the Publisher to which the tested Subscriber will be subscribed and tested against. - *

    - * By default an asynchronously signalling Publisher is provided, which will use {@link #createElement(int)} - * to generate elements type your Subscriber is able to consume. - *

    - * Sometimes you may want to implement your own custom custom helper Publisher - to validate behaviour of a Subscriber - * when facing a synchronous Publisher for example. If you do, it MUST emit the exact number of elements asked for - * (via the {@code elements} parameter) and MUST also must treat the following numbers of elements in these specific ways: - *

      - *
    • - * If {@code elements} is {@code Long.MAX_VALUE} the produced stream must be infinite. - *
    • - *
    • - * If {@code elements} is {@code 0} the {@code Publisher} should signal {@code onComplete} immediatly. - * In other words, it should represent a "completed stream". - *
    • - *
    - */ - @SuppressWarnings("unchecked") - public Publisher createHelperPublisher(long elements) { - final Function mkElement = new Function() { - @Override public T apply(Integer id) throws Throwable { - return createElement(id); - } - }; - - if (elements > Integer.MAX_VALUE) return new InfiniteHelperPublisher(mkElement, publisherExecutorService()); - else return new HelperPublisher(0, (int) elements, mkElement, publisherExecutorService()); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java deleted file mode 100644 index 67bd47d67d4..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow; - -import org.reactivestreams.Publisher; -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; - -import java.util.concurrent.Flow; - -/** - * Provides tests for verifying a Java 9+ {@link java.util.concurrent.Flow.Publisher} specification rules. - * - * @see java.util.concurrent.Flow.Publisher - */ -public abstract class FlowPublisherVerification extends PublisherVerification { - - public FlowPublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - super(env, publisherReferenceGCTimeoutMillis); - } - - public FlowPublisherVerification(TestEnvironment env) { - super(env); - } - - @Override - final public Publisher createPublisher(long elements) { - final Flow.Publisher flowPublisher = createFlowPublisher(elements); - return FlowAdapters.toPublisher(flowPublisher); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a Publisher for a stream with exactly the given number of elements. - * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite. - */ - public abstract Flow.Publisher createFlowPublisher(long elements); - - @Override - final public Publisher createFailedPublisher() { - final Flow.Publisher failed = createFailedFlowPublisher(); - if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher - else return FlowAdapters.toPublisher(failed); - } - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you ignore these additional tests, return {@code null} from this method. - */ - public abstract Flow.Publisher createFailedFlowPublisher(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java deleted file mode 100644 index 810ba85d0ff..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow; - -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.SubscriberBlackboxVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules; - -import java.util.concurrent.Flow; - -/** - * Provides tests for verifying {@link java.util.concurrent.Flow.Subscriber} and {@link java.util.concurrent.Flow.Subscription} - * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing). - * - * This verification is NOT able to check many of the rules of the spec, and if you want more - * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification} - * instead. - * - * @see java.util.concurrent.Flow.Subscriber - * @see java.util.concurrent.Flow.Subscription - */ -public abstract class FlowSubscriberBlackboxVerification extends SubscriberBlackboxVerification - implements SubscriberBlackboxVerificationRules { - - protected FlowSubscriberBlackboxVerification(TestEnvironment env) { - super(env); - } - - @Override - public final void triggerRequest(Subscriber subscriber) { - triggerFlowRequest(FlowAdapters.toFlowSubscriber(subscriber)); - } - /** - * Override this method if the {@link java.util.concurrent.Flow.Subscriber} implementation you are verifying - * needs an external signal before it signals demand to its Publisher. - * - * By default this method does nothing. - */ - public void triggerFlowRequest(Flow.Subscriber subscriber) { - // this method is intentionally left blank - } - - @Override - public final Subscriber createSubscriber() { - return FlowAdapters.toSubscriber(createFlowSubscriber()); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link Flow.Subscriber} instance to be subjected to the testing logic. - */ - abstract public Flow.Subscriber createFlowSubscriber(); - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java deleted file mode 100644 index 9b382700d4f..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow; - -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.Subscriber; -import org.reactivestreams.tck.SubscriberWhiteboxVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; - -import java.util.concurrent.Flow; - -/** - * Provides whitebox style tests for verifying {@link java.util.concurrent.Flow.Subscriber} - * and {@link java.util.concurrent.Flow.Subscription} specification rules. - * - * @see java.util.concurrent.Flow.Subscriber - * @see java.util.concurrent.Flow.Subscription - */ -public abstract class FlowSubscriberWhiteboxVerification extends SubscriberWhiteboxVerification - implements SubscriberWhiteboxVerificationRules { - - protected FlowSubscriberWhiteboxVerification(TestEnvironment env) { - super(env); - } - - @Override - final public Subscriber createSubscriber(WhiteboxSubscriberProbe probe) { - return FlowAdapters.toSubscriber(createFlowSubscriber(probe)); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - * - * In order to be meaningfully testable your Subscriber must inform the given - * `WhiteboxSubscriberProbe` of the respective events having been received. - */ - protected abstract Flow.Subscriber createFlowSubscriber(WhiteboxSubscriberProbe probe); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java deleted file mode 100644 index 20dd71499eb..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow; - -import org.reactivestreams.*; -import org.reactivestreams.tck.IdentityProcessorVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; - -import java.util.concurrent.Flow; - -public abstract class IdentityFlowProcessorVerification extends IdentityProcessorVerification - implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules { - - public IdentityFlowProcessorVerification(TestEnvironment env) { - super(env); - } - - public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - super(env, publisherReferenceGCTimeoutMillis); - } - - public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) { - super(env, publisherReferenceGCTimeoutMillis, processorBufferSize); - } - - /** - * By implementing this method, additional TCK tests concerning a "failed" Flow publishers will be run. - * - * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you want to ignore these additional tests, return {@code null} from this method. - */ - protected abstract Flow.Publisher createFailedFlowPublisher(); - - /** - * This is the main method you must implement in your test incarnation. - * It must create a {@link Flow.Processor}, which simply forwards all stream elements from its upstream - * to its downstream. It must be able to internally buffer the given number of elements. - * - * @param bufferSize number of elements the processor is required to be able to buffer. - */ - protected abstract Flow.Processor createIdentityFlowProcessor(int bufferSize); - - @Override - public final Processor createIdentityProcessor(int bufferSize) { - return FlowAdapters.toProcessor(createIdentityFlowProcessor(bufferSize)); - } - - @Override - public final Publisher createFailedPublisher() { - Flow.Publisher failed = createFailedFlowPublisher(); - if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher - else return FlowAdapters.toPublisher(failed); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java deleted file mode 100644 index 120fd43e694..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.Executor; - -import org.reactivestreams.example.unicast.AsyncIterablePublisher; - -public class HelperPublisher extends AsyncIterablePublisher { - - public HelperPublisher(final int from, final int to, final Function create, final Executor executor) { - super(new Iterable() { - { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); } - @Override public Iterator iterator() { - return new Iterator() { - private int at = from; - @Override public boolean hasNext() { return at < to; } - @Override public T next() { - if (!hasNext()) return Collections.emptyList().iterator().next(); - else try { - return create.apply(at++); - } catch (Throwable t) { - throw new IllegalStateException(String.format("Failed to create element for id %d!", at - 1), t); - } - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java deleted file mode 100644 index e3cfccb5978..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -import org.reactivestreams.example.unicast.AsyncIterablePublisher; - -import java.util.Iterator; -import java.util.concurrent.Executor; - -public class InfiniteHelperPublisher extends AsyncIterablePublisher { - - public InfiniteHelperPublisher(final Function create, final Executor executor) { - super(new Iterable() { - @Override public Iterator iterator() { - return new Iterator() { - private int at = 0; - - @Override public boolean hasNext() { return true; } - @Override public T next() { - try { - return create.apply(at++); // Wraps around on overflow - } catch (Throwable t) { - throw new IllegalStateException( - String.format("Failed to create element in %s for id %s!", getClass().getSimpleName(), at - 1), t); - } - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java deleted file mode 100644 index ee315931f72..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - - -/** - * Copy of scala.control.util.NonFatal in order to not depend on scala-library - */ -public class NonFatal { - private NonFatal() { - // no instances, please. - } - - /** - * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal - * - * @param t throwable to be matched for fatal-ness - * @return true if is a non-fatal throwable, false otherwise - */ - public static boolean isNonFatal(Throwable t) { - if (t instanceof StackOverflowError) { - // StackOverflowError ok even though it is a VirtualMachineError - return true; - } else if (t instanceof VirtualMachineError || - t instanceof ThreadDeath || - t instanceof InterruptedException || - t instanceof LinkageError) { - // VirtualMachineError includes OutOfMemoryError and other fatal errors - return false; - } else { - return true; - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java deleted file mode 100644 index d191fe0a39d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -import java.util.NoSuchElementException; - -// simplest possible version of Scala's Option type -public abstract class Optional { - - private static final Optional NONE = new Optional() { - @Override - public Object get() { - throw new NoSuchElementException(".get call on None!"); - } - - @Override - public boolean isEmpty() { - return true; - } - }; - - private Optional() { - } - - @SuppressWarnings("unchecked") - public static Optional empty() { - return (Optional) NONE; - } - - @SuppressWarnings("unchecked") - public static Optional of(T it) { - if (it == null) return (Optional) Optional.NONE; - else return new Some(it); - } - - public abstract T get(); - - public abstract boolean isEmpty(); - - public boolean isDefined() { - return !isEmpty(); - } - - public static class Some extends Optional { - private final T value; - - Some(T value) { - this.value = value; - } - - @Override - public T get() { - return value; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public String toString() { - return String.format("Some(%s)", value); - } - } - - @Override - public String toString() { - return "None"; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java deleted file mode 100644 index 3af007cb9e1..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -/** - * Internal TCK use only. - * Add / Remove tests for PublisherVerification here to make sure that they arre added/removed in the other places. - */ -public interface PublisherVerificationRules { - /** - * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} - * returns a non-negative value. - */ - void required_validate_maxElementsFromPublisher() throws Exception; - /** - * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#boundedDepthOfOnNextAndRequestRecursion()} - * returns a positive value. - */ - void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception; - /** - * Asks for a {@code Publisher} that should emit exactly one item and complete (both within a - * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()}) - * in response to a request(1). - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} returns zero. - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
    • - *
    • if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call - * in response to the test subscriber or by default to their upstream,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s),
    • - *
    • if the {@code Publisher} implementation works for a consumer that calls {@code request(1)},
    • - *
    • if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests,
    • - *
    • that the {@code Publisher} implementation does not emit more than the allowed elements (exactly one).
    • - *
    - */ - void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable; - /** - * Asks for a {@code Publisher} that should emit exactly three items and complete (all within a - * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()}). - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * The tests requests one-by-one and verifies each single response item arrives in time. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
    • - *
    • if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call - * in response to the test subscriber or by default to their upstream,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s),
    • - *
    • if the {@code Publisher} implementation works for a subscriber that calls {@code request(1)} after consuming an item,
    • - *
    • if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests.
    • - *
    - */ - void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable; - /** - * Asks for a {@code Publisher} that responds to a request pattern of 0 (not requesting upfront), 1, 1 and 2 - * in a timely manner. - *

    - * Verifies rule: 1.1 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5. - *

    - * This test ensures that the {@code Publisher} implementation correctly responds to {@code request()} calls that in - * total are less than the number of elements this {@code Publisher} could emit (thus the completion event won't be emitted). - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable; - /** - * Asks for a short {@code Publisher} and verifies that requesting once and with more than the length (but bounded) results in the - * correct number of items to be emitted (i.e., length 3 and request 10) followed by an {@code onComplete} signal. - *

    - * Verifies rule: 1.2 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * This test ensures that the {@code Publisher} implementation can deal with larger requests than the number of items it can produce. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass.
    • - *
    - */ - void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable; - /** - * Asks for a short {@code Publisher} (i.e., length 10), repeatedly subscribes to this {@code Publisher}, requests items - * one by one and verifies the {@code Publisher} calls the {@code onXXX} methods non-overlappingly. - *

    - * Verifies rule: 1.3 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

    - * Note that this test is probabilistic, that is, may not capture any concurrent invocation in a {@code Publisher} implementation. - * Note also that this test is sensitive to cases when a {@code request()} call in {@code onSubscribe()} triggers an asynchronous - * call to the other {@code onXXX} methods. In contrast, the test allows synchronous call chain of - * {@code onSubscribe -> request -> onNext}. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if a {@code request()} call from {@code onSubscribe()} could trigger an asynchronous call to {@code onNext()} and if so, make sure - * such {@code request()} calls are deferred until the call to {@code onSubscribe()} returns normally.
    • - *
    - */ - void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable; - /** - * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once - * followed by a single call to {@code onError()} without receiving any requests and otherwise - * not throwing any exception. - *

    - * Verifies rule: 1.4 - *

    - * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null. - *

    - * If this test fails, the following could be checked within the error {@code Publisher} implementation: - *

      - *
    • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
    • - *
    • if the {@code Publisher} implementation does signal an {@code onSubscribe} before signalling {@code onError},
    • - *
    • if the {@code Publisher} implementation is able to emit an {@code onError} without requests,
    • - *
    • if the {@code Publisher} is non-empty as this test requires a {@code Publisher} to signal an - * {@code onError} eagerly.
    • - *
    - */ - void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable; - /** - * Asks for a short {@code Publisher} (i.e., length 3) and verifies, after requesting one by one, the sequence - * completes normally. - *

    - * Verifies rule: 1.5 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * Note that the tests requests 1 after the items have been received and before expecting an {@code onComplete} signal. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    - */ - void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable; - /** - * Asks for an empty {@code Publisher} (i.e., length 0) and verifies it completes in a timely manner. - *

    - * Verifies rule: 1.5 - *

    - * Note that the tests requests 1 before expecting an {@code onComplete} signal. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • if the {@code Publisher} is non-empty as this test requires a {@code Publisher} without items.
    • - *
    - */ - void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable; - /** - * Currently, this test is skipped because it is unclear this rule can be effectively checked - * on a {@code Publisher} instance without looking into or hooking into the implementation of it. - *

    - * Verifies rule: 1.6 - */ - void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and checks if requesting after the terminal event doesn't - * lead to more items or terminal signals to be emitted. - *

    - * Verifies rule: 1.7 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

    - * The tests requests more items than the expected {@code Publisher} length upfront and some more items after its completion. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • the indication for the terminal state is properly persisted and a request call can't trigger emission of more items or another - * terminal signal.
    • - *
    - */ - void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable; - /** - * Currently, this test is skipped, although it is possible to validate an error {@code Publisher} along - * the same lines as {@link #required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled()}. - *

    - * Verifies rule: 1.7 - */ - void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable; - /** - * Currently, this test is skipped because there was no agreement on how to verify its "eventually" requirement. - *

    - * Verifies rule: 1.8 - */ - void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable; - /** - * Asks for an empty {@code Publisher} and verifies if {@code onSubscribe} signal was emitted before - * any other {@code onNext}, {@code onError} or {@code onComplete} signal. - *

    - * Verifies rule: 1.9 - *

    - * Note that this test doesn't request anything, however, an {@code onNext} is not considered as a failure. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s).
    • - *
    - */ - void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable; - /** - * Currently, this test is skipped because there is no common agreement on what is to be considered a fatal exception and - * besides, {@code Publisher.subscribe} is only allowed throw a {@code NullPointerException} and any other - * exception would require looking into or hooking into the implementation of the {@code Publisher}. - *

    - * Verifies rule: 1.9 - */ - void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable; - /** - * Asks for an empty {@code Publisher} and calls {@code subscribe} on it with {@code null} that should result in - * a {@code NullPointerException} to be thrown. - *

    - * Verifies rule: 1.9 - *

    - * If this test fails, check if the {@code subscribe()} implementation has an explicit null check (or a method dereference - * on the {@code Subscriber}), especially if the incoming {@code Subscriber} is wrapped or stored to be used later. - */ - void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable; - /** - * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once - * followed by a single call to {@code onError()} without receiving any requests. - *

    - * Verifies rule: 1.9 - *

    - * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null. - *

    - * The difference between this test and {@link #optional_spec104_mustSignalOnErrorWhenFails()} is that there is - * no explicit verification if exceptions were thrown in addition to the regular {@code onSubscribe+onError} signal pair. - *

    - * If this test fails, the following could be checked within the error {@code Publisher} implementation: - *

      - *
    • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
    • - *
    • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
    • - *
    • if the {@code Publisher} implementation is able to emit an {@code onError} without requests,
    • - *
    • if the {@code Publisher} is non-empty as this test expects a {@code Publisher} without items.
    • - *
    - */ - void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable; - /** - * Currently, this test is skipped because enforcing rule §1.10 requires unlimited retention and reference-equal checks on - * all incoming {@code Subscriber} which is generally infeasible, plus reusing the same {@code Subscriber} instance is - * better detected (or ignored) inside {@code Subscriber.onSubscribe} when the method is called multiple times. - *

    - * Verifies rule: 1.10 - */ - void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and subscribes to it twice, without consuming with either - * {@code Subscriber} instance - * (i.e., no requests are issued). - *

    - * Verifies rule: 1.11 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

    - * Note that this test ignores what signals the {@code Publisher} emits. Any exception thrown through non-regular - * means will indicate a skipped test. - */ - void optional_spec111_maySupportMultiSubscribe() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and subscribes to it twice. - * Each {@code Subscriber} requests for 1 element and checks if onNext or onComplete signals was received. - *

    - * Verifies rule: 1.11, - * and depends on valid implementation of rule 1.5 - * in order to verify this. - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

    - * Any exception thrown through non-regular means will indicate a skipped test. - */ - void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 5), subscribes 3 {@code Subscriber}s to it, requests with different - * patterns and checks if all 3 received the same events in the same order. - *

    - * Verifies rule: 1.11 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5. - *

    - * The request pattern for the first {@code Subscriber} is (1, 1, 2, 1); for the second is (2, 3) and for the third is (3, 1, 1). - *

    - * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

    - * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items - * upfront with each and verifies they all received the same items in the same order (but does not verify they all complete). - *

    - * Verifies rule: 1.11 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

    - * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items - * upfront with each and verifies they all received the same items in the same order followed by an {@code onComplete} signal. - *

    - * Verifies rule: 1.11 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

    - * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 6), requests several times from within {@code onSubscribe} and then requests - * one-by-one from {@code onNext}. - *

    - * Verifies rule: 3.2 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 6. - *

    - * The request pattern is 3 x 1 from within {@code onSubscribe} and one from within each {@code onNext} invocation. - *

    - * The test consumes the {@code Publisher} but otherwise doesn't verify the {@code Publisher} completes (however, it checks - * for errors). - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable; - /** - * Asks for a {@code Publisher} with length equal to the value returned by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1, - * calls {@code request(1)} externally and then from within {@code onNext} and checks if the stack depth did not increase beyond the - * amount permitted by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()}. - *

    - * Verifies rule: 3.3 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than - * {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the implementation doesn't allow unbounded recursion when {@code request()} is called from within {@code onNext}, i.e., the lack of - * reentrant-safe state machine around the request amount (such as a for loop with a bound on the parameter {@code n} that calls {@code onNext}). - *
    - */ - void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable; - /** - * Currently, this test is skipped because a {@code request} could enter into a synchronous computation via {@code onNext} - * legally and otherwise there is no common agreement how to detect such heavy computation reliably. - *

    - * Verifies rule: 3.4 - */ - void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception; - /** - * Currently, this test is skipped because there is no reliable agreed upon way to detect a heavy computation. - *

    - * Verifies rule: 3.5 - */ - void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception; - /** - * Asks for a short {@code Publisher} (length 3) and verifies that cancelling without requesting anything, then requesting - * items should result in no signals to be emitted. - *

    - * Verifies rule: 3.6 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * The post-cancellation request pattern is (1, 1, 1). - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
    • - *
    - */ - void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and verifies that without requesting anything, cancelling the sequence - * multiple times should result in no signals to be emitted and should result in an thrown exception. - *

    - * Verifies rule: 3.7 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
    • - *
    - */ - void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a {@code request(0)} which should trigger an {@code onError} call - * with an {@code IllegalArgumentException}. - *

    - * Verifies rule: 3.9 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

    - * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

    - * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
    - */ - void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should - * trigger an {@code onError} call with an {@code IllegalArgumentException}. - *

    - * Verifies rule: 3.9 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

    - * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

    - * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
    - */ - void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should - * trigger an {@code onError} call with an {@code IllegalArgumentException}. - *

    - * Verifies rule: 3.9 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

    - * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

    - * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
    - */ - void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 20), requests some items (less than the length), consumes one item then - * cancels the sequence and verifies the publisher emitted at most the requested amount and stopped emitting (or terminated). - *

    - * Verifies rule: 3.12 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 20. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
    • - *
    - */ - void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) requests and consumes one element from it, cancels the {@code Subscription} - * , calls {@code System.gc()} and then checks if all references to the test {@code Subscriber} has been dropped (by checking - * the {@code WeakReference} has been emptied). - *

    - * Verifies rule: 3.13 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
    • - *
    • the {@code Publisher} stores the {@code Subscriber} reference somewhere which is then not cleaned up when the {@code Subscriber} is cancelled. - * Note that this may happen on many code paths in a {@code Publisher}, for example in an emission loop that terminates because of the - * {@code cancel} signal or because reaching a terminal state. Note also that eagerly nulling {@code Subscriber} references may not be necessary - * for this test to pass in case there is a self-contained chain of them (i.e., {@code Publisher.subscribe()} creates a chain of fresh - * {@code Subscriber} instances where each of them only references their downstream {@code Subscriber} thus the chain can get GC'd - * when the reference to the final {@code Subscriber} is dropped). - *
    - */ - void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it, verifying that the - * {@code Publisher} emits all of its items and completes normally - * and does not keep spinning attempting to fulfill the {@code Long.MAX_VALUE} demand by some means. - *

    - * Verifies rule: 3.17 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it in total (split across - * two {@code Long.MAX_VALUE / 2} and one {@code request(1)}), verifying that the - * {@code Publisher} emits all of its items and completes normally. - *

    - * Verifies rule: 3.17 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts) - * or not properly deducing the number of emitted items from the pending amount,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable; - /** - * Asks for a very long {@code Publisher} (up to {@code Integer.MAX_VALUE}), requests {@code Long.MAX_VALUE - 1} after - * each received item and expects no failure due to a potential overflow in the pending emission count while consuming - * 10 items and cancelling the sequence. - *

    - * Verifies rule: 3.17 - *

    - * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than {@code Integer.MAX_VALUE}. - *

    - * The request pattern is one {@code request(1)} upfront and ten {@code request(Long.MAX_VALUE - 1)} after. - *

    - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

      - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
    • - *
    • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
    • - *
    • if the {@code Publisher} implementation considers the cumulative request amount it receives,
    • - *
    • if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts) - * or not properly deducing the number of emitted items from the pending amount,
    • - *
    • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
    • - *
    - */ - void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java deleted file mode 100644 index 6526e238621..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -import org.reactivestreams.tck.SubscriberBlackboxVerification; - -/** - * Internal TCK use only. - * Add / Remove tests for SubscriberBlackboxVerification here to make sure that they arre added/removed in the other places. - */ -public interface SubscriberBlackboxVerificationRules { - /** - * Asks for a {@code Subscriber} instance, expects it to call {@code request()} in - * a timely manner and signals as many {@code onNext} items as the very first request - * amount specified by the {@code Subscriber}. - *

    - * Verifies rule: 2.1 - *

    - * Notes: - *

      - *
    • This test emits the number of items requested thus the {@code Subscriber} implementation - * should not request too much.
    • - *
    • Only the very first {@code request} amount is considered.
    • - *
    • This test doesn't signal {@code onComplete} after the first set of {@code onNext} signals - * has been emitted and may cause resource leak in - * {@code Subscriber}s that expect a finite {@code Publisher}.
    • - *
    • The test ignores cancellation from the {@code Subscriber} and emits the requested amount regardless.
    • - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} requires external stimulus to begin requesting; override the - * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method - * in this case,
    • - *
    • the {@code TestEnvironment} has large enough timeout specified in case the {@code Subscriber} has some time-delay behavior,
    • - *
    • if the {@code Subscriber} requests zero or a negative value in some circumstances,
    • - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onNext} methods. - *
    - */ - void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable; - /** - * Currently, this test is skipped because there is no agreed upon approach how - * to detect if the {@code Subscriber} really goes async or just responds in - * a timely manner. - *

    - * Verifies rule: 2.2 - */ - void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onComplete} synchronously, - * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s - * {@code onComplete} implementation. - *

    - * Verifies rule: 2.3 - *

    - * Notes: - *

      - *
    • The test checks for the presensce of method named "onComplete" in the current stacktrace when handling - * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • no calls happen to {@code request} or {@code cancel} in response to an {@code onComplete} - * directly or indirectly,
    • - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
    - */ - void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onError} synchronously, - * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s - * {@code onComplete} implementation. - *

    - * Verifies rule: 2.3 - *

    - * Notes: - *

      - *
    • The test checks for the presensce of method named "onError" in the current stacktrace when handling - * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • no calls happen to {@code request} or {@code cancel} in response to an {@code onError} - * directly or indirectly,
    • - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
    - */ - void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable; - /** - * Currently, this test is skipped because there is no way to check what the {@code Subscriber} "considers" - * since rule §2.3 forbids interaction from within the {@code onError} and {@code onComplete} methods. - *

    - * Verifies rule: 2.4 - *

    - * Notes: - *

      - *
    • It would be possible to check if there was an async interaction with the test's {@code Subscription} - * within a grace period but such check is still not generally decisive.
    • - *
    - */ - void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception; - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} twice synchronously and expects the second {@code Subscription} gets - * cancelled in a timely manner and without any calls to its {@code request} method. - *

    - * Verifies rule: 2.5 - *

    - * Notes: - *

      - *
    • The test doesn't signal any other events than {@code onSubscribe} and may cause resource leak in - * {@code Subscriber}s that expect a finite {@code Publisher}. - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscribe.onSubscribe} implementation actually tries to detect multiple calls to it,
    • - *
    • if the second {@code Subscription} is cancelled asynchronously and that takes longer time than - * the {@code TestEnvironment}'s timeout permits.
    • - *
    - */ - void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception; - - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * to make it cancel the {@code Subscription} for some external condition. - *

    - * Verifies rule: 2.6 - */ - void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * to issue requests based on external stimulus. - *

    - * Verifies rule: 2.7 - */ - void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception; - /** - * Currently, this test is skipped because there is no way to make the {@code Subscriber} implementation - * cancel the test's {@code Subscription} and check the outcome of sending {@code onNext}s after such - * cancel. - *

    - * Verifies rule: 2.8 - */ - void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable; - /** - * Asks for a {@code Subscriber}, expects it to request some amount and in turn be able to receive an {@code onComplete} - * synchronously from the {@code request} call without any {@code onNext} signals before that. - *

    - * Verifies rule: 2.9 - *

    - * Notes: - *

      - *
    • The test ignores cancellation from the {@code Subscriber}.
    • - *
    • Invalid request amounts are ignored by this test.
    • - *
    • Concurrent calls to the test's {@code Subscription.request()} must be externally synchronized, otherwise - * such case results probabilistically in multiple {@code onComplete} calls by the test.
    • - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
    • if the {@code Subscriber} requires external stimulus to begin requesting; override the - * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method - * in this case,
    • - *
    - */ - void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable; - /** - * Asks for a {@code Subscriber} and expects it to handle {@code onComplete} independent of whether the {@code Subscriber} - * requests items or not. - *

    - * Verifies rule: 2.9 - *

    - * Notes: - *

      - *
    • Currently, the test doesn't call {@code onSubscribe} on the {@code Subscriber} which violates §1.9. - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
    - */ - void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. - *

    - * Verifies rule: 2.10 - *

    - * Notes: - *

      - *
    • Despite the method name, the test doesn't expect a request signal from {@code Subscriber} and emits the - * {@code onError} signal anyway. - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
    - */ - void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable; - - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. - *

    - * Verifies rule: 2.10 - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
    - */ - void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable; - - /** - * Currently, this test is skipped because it would require analyzing what the {@code Subscriber} implementation - * does. - *

    - * Verifies rule: 2.11 - */ - void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception; - /** - * Currently, this test is skipped because the test for - * {@link #required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal §2.5} - * is in a better position to test for handling the reuse of the same {@code Subscriber}. - *

    - * Verifies rule: 2.12 - *

    - * Notes: - *

      - *
    • In addition to §2.5, this rule could be better verified when testing a {@code Publisher}'s subscription behavior. - *
    - */ - void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable; - /** - * Currently, this test is skipped because it would require more control over the {@code Subscriber} to - * fail internally in response to a set of legal event emissions, not throw any exception from the {@code Subscriber} - * methods and have it cancel the {@code Subscription}. - *

    - * Verifies rule: 2.13 - */ - void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception; - /** - * Asks for a {@code Subscriber} and signals an {@code onSubscribe} event with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onSubscribe} method. - *

    - * Verifies rule: 2.13 - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onSubscribe} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
    - */ - void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a - * {@code onNext} with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onNext} method. - *

    - * Verifies rule: 2.13 - *

    - * Notes: - *

      - *
    • The test ignores cancellation and requests from the {@code Subscriber} and emits the {@code onNext} - * signal with a {@code null} parameter anyway.
    • - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
    - */ - void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a - * {@code onError} with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onError} method. - *

    - * Verifies rule: 2.13 - *

    - * Notes: - *

      - *
    • The test ignores cancellation from the {@code Subscriber} and emits the {@code onError} - * signal with a {@code null} parameter anyway.
    • - *
    - *

    - * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

      - *
    • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
    - */ - void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Currently, this test is skipped because there is no agreed upon way for specifying, enforcing and testing - * a {@code Subscriber} with an arbitrary context. - *

    - * Verifies rule: 3.1 - */ - void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception; - /** - * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

    - * Verifies rule: 3.8 - */ - void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable; - /** - * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

    - * Verifies rule: 3.10 - *

    - * Notes: - *

      - *
    • This could be tested with a synchronous source currently not available within the TCK.
    • - *
    - */ - void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception; - /** - * Currently, this test is skipped because signal production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

    - * Verifies rule: 3.11 - *

    - * Notes: - *

      - *
    • Tests {@link #required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() §2.9} - * and {@link #required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() §2.10} are - * supposed to cover this case from the {@code Subscriber's} perspective.
    • - *
    - */ - void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception; - /** - * Currently, this test is skipped because it is the responsibility of the {@code Publisher} deal with the case - * that all subscribers have cancelled their subscription. - *

    - * Verifies rule: 3.14 - *

    - * Notes: - *

      - *
    • The specification lists this as an optional behavior because only some {@code Publisher} implementations - * (most likely {@code Processor}s) would coordinate with multiple {@code Subscriber}s.
    • - *
    - */ - void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response - * to an exception thrown from {@code Subscription.cancel}. - *

    - * Verifies rule: 3.15 - */ - void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response - * to an exception thrown from {@code Subscription.request}. - *

    - * Verifies rule: 3.16 - */ - void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java deleted file mode 100644 index e8f1e835a06..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.reactivestreams.tck.flow.support; - -/** - * Internal TCK use only. - * Add / Remove tests for PublisherVerificaSubscriberWhiteboxVerification here to make sure that they arre added/removed in the other places. - */ -public interface SubscriberWhiteboxVerificationRules { - void required_exerciseWhiteboxHappyPath() throws Throwable; - void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable; - void untested_spec202_shouldAsynchronouslyDispatch() throws Exception; - void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable; - void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable; - void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception; - void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable; - void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception; - void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception; - void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable; - void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable; - void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable; - void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable; - void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable; - void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception; - void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable; - void untested_spec213_failingOnSignalInvocation() throws Exception; - void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception; - void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable; - void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception; - void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception; - void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception; - void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception; - void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception; -} diff --git a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java index e83381c17e3..969ab72be55 100644 --- a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java +++ b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java @@ -112,21 +112,22 @@ public void test(String uri, boolean sameClient) { .join(); fail("Expected to throw"); } catch (CompletionException ce) { - Throwable t = getCompletionCause(ce); + final Throwable t = getCompletionCause(ce); if (!(t instanceof WebSocketHandshakeException)) { throw new AssertionError("Unexpected exception", t); } - WebSocketHandshakeException wse = (WebSocketHandshakeException) t; + final WebSocketHandshakeException wse = (WebSocketHandshakeException) t; assertNotNull(wse.getResponse()); - assertNotNull(wse.getResponse().body()); - assertEquals(wse.getResponse().body().getClass(), String.class); - String body = (String)wse.getResponse().body(); - String expectedBody = "/?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; - assertEquals(body, expectedBody); - out.println("Status code is " + wse.getResponse().statusCode()); - out.println("Response is " + body); + assertNotNull(wse.getResponse().uri()); assertNotNull(wse.getResponse().statusCode()); + final String rawQuery = wse.getResponse().uri().getRawQuery(); + final String expectedRawQuery = "&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; + assertEquals(rawQuery, expectedRawQuery); + final String body = (String) wse.getResponse().body(); + final String expectedBody = "/?" + expectedRawQuery; + assertEquals(body, expectedBody); out.println("Status code is " + wse.getResponse().statusCode()); + out.println("Response is " + wse.getResponse()); assertEquals(wse.getResponse().statusCode(), 400); } } diff --git a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java index 62a48b26b25..afd067605ae 100644 --- a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java +++ b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java @@ -24,7 +24,7 @@ import jdk.test.lib.RandomFactory; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.io.IOException; import java.nio.ByteBuffer; @@ -78,7 +78,7 @@ public static void main(String[] args) throws IOException { try (FileChannel fc = FileChannel.open(p, READ, WRITE)) { MemorySegment mappedMemorySegment = fc.map(FileChannel.MapMode.READ_WRITE, 0, p.toFile().length(), - MemorySession.openImplicit()); + SegmentScope.auto()); MemorySegment target = mappedMemorySegment.asSlice(BASE, EXTRA); if (!target.asByteBuffer().equals(bb)) { throw new RuntimeException("Expected buffers to be equal"); diff --git a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java index 3a817cd9e28..b06af75c48d 100644 --- a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java +++ b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java @@ -30,8 +30,9 @@ import java.io.File; import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; @@ -61,21 +62,21 @@ public class MapToMemorySegmentTest { @Test(expectedExceptions = UnsupportedOperationException.class) public void testCustomFileChannel() throws IOException { - var session = MemorySession.openConfined(); + var arena = Arena.openConfined(); var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ); var fileChannel = new CustomFileChannel(fc); - try (session; fileChannel){ - fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, session); + try (arena; fileChannel){ + fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena.scope()); } } @Test public void testCustomFileChannelOverride() throws IOException { - var session = MemorySession.openConfined(); + var arena = Arena.openConfined(); var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ); var fileChannel = new CustomFileChannelOverride(fc); - try (session; fileChannel){ - fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, session); + try (arena; fileChannel){ + fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena.scope()); } } @@ -160,10 +161,10 @@ static class CustomFileChannelOverride extends CustomFileChannel { public CustomFileChannelOverride(FileChannel fc) { super(fc); } @Override - public MemorySegment map(MapMode mode, long offset, long size, MemorySession session) + public MemorySegment map(MapMode mode, long offset, long size, SegmentScope scope) throws IOException, UnsupportedOperationException { - return fc.map(mode, offset, size, session); + return fc.map(mode, offset, size, scope); } } } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Service.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Service.java new file mode 100644 index 00000000000..fa256b9d18a --- /dev/null +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Service.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 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. + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.nio.ByteBuffer; +import java.nio.channels.Channel; +import java.nio.channels.SocketChannel; + +public class CheckIPv6Service { + + static boolean isIPv6Available() { + try { + new ServerSocket(0,0, InetAddress.getByAddress(new byte[16])).close(); + return true; + } catch (Exception e) { + return false; + } + } + + private static void doIt(SocketChannel sc, int closeAfter, int delay) throws IOException { + ByteBuffer bb = ByteBuffer.allocate(1024); + int total = 0; + for (;;) { + bb.clear(); + int n = sc.read(bb); + if (n < 0) { + break; + } + total += n; + + // echo + bb.flip(); + sc.write(bb); + + // close after X bytes? + if (closeAfter > 0 && total >= closeAfter) { + break; + } + } + + sc.close(); + if (delay > 0) { + try { + Thread.currentThread().sleep(delay); + } catch (InterruptedException x) { } + } + } + + public static void main(String args[]) throws IOException { + // check if IPv6 is available; if it is, behave like EchoService. + if (!isIPv6Available()) { + return; + } + + Channel c = System.inheritedChannel(); + if (c == null) { + return; + } + + if (c instanceof SocketChannel) { + int closeAfter = 0; + int delay = 0; + if (args.length > 0) { + closeAfter = Integer.parseInt(args[0]); + } + if (args.length > 1) { + delay = Integer.parseInt(args[1]); + } + doIt((SocketChannel)c, closeAfter, delay); + } + } + +} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Test.java similarity index 52% rename from test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java rename to test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Test.java index 555906461a2..50643710dc4 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/CheckIPv6Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -21,29 +21,36 @@ * questions. */ -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; +import java.io.IOException; -import java.util.concurrent.Flow.Publisher; -import java.util.stream.LongStream; -import java.util.stream.Stream; +/** + * This test verifies that a service launched with IPv4 inherited channel + * can use IPv6 networking; this used to be impossible, see JDK-6914801 + */ +public class CheckIPv6Test { -/* See TckDriver.java for more information */ -public class SPublisherOfStream - extends FlowPublisherVerification { + private static int failures = 0; - public SPublisherOfStream() { - super(new TestEnvironment(450L)); - } + private static final String SERVICE = "CheckIPv6Service"; - @Override - public Publisher createFlowPublisher(long nElements) { - Stream s = LongStream.range(0, nElements).boxed(); - return S.publisherOfStream(s); - } + public static void main(String args[]) throws IOException { - @Override - public Publisher createFailedFlowPublisher() { - return null; + if (!CheckIPv6Service.isIPv6Available()) { + System.out.println("IPv6 not available. Test skipped."); + return; + } + + try { + EchoTest.TCPEchoTest(SERVICE); + System.out.println("IPv6 test passed."); + } catch (Exception x) { + System.err.println(x); + failures++; + } + + if (failures > 0) { + throw new RuntimeException("Test failed - see log for details"); + } } + } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java index 9931f42c458..8ce0efa4c8d 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/EchoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -57,8 +57,8 @@ public class EchoTest { * a reply (with timeout). Once the reply is received it is checked to ensure * that it matches the original message. */ - private static void TCPEchoTest() throws IOException { - SocketChannel sc = Launcher.launchWithInetSocketChannel(ECHO_SERVICE, null); + static void TCPEchoTest(String echoService) throws IOException { + SocketChannel sc = Launcher.launchWithInetSocketChannel(echoService, null); String msg = "Where's that damn torpedo?"; int repeat = 100; @@ -160,7 +160,7 @@ public static void main(String args[]) throws IOException { // TCP echo try { - TCPEchoTest(); + TCPEchoTest(ECHO_SERVICE); System.out.println("TCP echo test passed."); } catch (Exception x) { System.err.println(x); diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java index f4076af9b01..813bb839bfc 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4673940 4930794 8211842 + * @bug 4673940 4930794 8211842 6914801 * @summary Unit tests for inetd feature * @requires (os.family == "linux" | os.family == "mac") * @library /test/lib @@ -35,6 +35,7 @@ * jdk.test.lib.process.* * UnixSocketTest StateTest StateTestService EchoTest EchoService * UnixDomainChannelTest CloseTest Launcher Util + * CheckIPv6Test CheckIPv6Service * @run testng/othervm/native InheritedChannelTest * @key intermittent */ @@ -79,6 +80,7 @@ public Object[][] testCases() { { "UnixSocketTest", List.of(UnixSocketTest.class.getName())}, { "StateTest", List.of(StateTest.class.getName(), "-Dtest.classes="+TEST_CLASSES)}, { "EchoTest", List.of(EchoTest.class.getName()) }, + { "CheckIPv6Test", List.of(CheckIPv6Test.class.getName()) }, { "CloseTest", List.of(CloseTest.class.getName()) }, // run StateTest with a SecurityManager set diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java index 8e166582819..ba1473a2d06 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.nio.channels.SocketChannel; import java.nio.file.Files; +import static java.net.StandardProtocolFamily.INET; import static java.net.StandardProtocolFamily.UNIX; public class Launcher { @@ -100,11 +101,18 @@ public static SocketChannel launchWithInetSocketChannel(String className, String... args) throws IOException { - try (ServerSocketChannel ssc = ServerSocketChannel.open()) { - ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); - InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), - ssc.socket().getLocalPort()); - SocketChannel sc1 = SocketChannel.open(isa); + ServerSocketChannel ch; + try { + ch = ServerSocketChannel.open(INET); + System.out.println("Using INET (IPv4) channel"); + } catch (Exception e) { + ch = ServerSocketChannel.open(); + System.out.println("Using default channel (probably IPv6)"); + } + try (ServerSocketChannel ssc = ch) { + ssc.socket().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + System.out.println("Socket bound to " + ssc.getLocalAddress()); + SocketChannel sc1 = SocketChannel.open(ssc.getLocalAddress()); try (SocketChannel sc2 = ssc.accept()) { launch(className, options, args, Util.getFD(sc2)); } diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 13cf1d135ad..8bf86320b3f 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 8129632 8129633 8162624 8146215 8162745 8273655 8274171 8287237 + * @bug 4313887 8129632 8129633 8162624 8146215 8162745 8273655 8274171 8287237 8297609 * @summary Unit test for probeContentType method * @library ../.. * @build Basic SimpleFileTypeDetector @@ -187,6 +187,7 @@ public static void main(String[] args) throws IOException { new ExType("xls", List.of("application/vnd.ms-excel")), new ExType("xlsx", List.of("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")), new ExType("7z", List.of("application/x-7z-compressed")), + new ExType("wasm", List.of("application/wasm")), }; failures += checkContentTypes(exTypes); diff --git a/test/jdk/java/nio/file/Path/Extensions.java b/test/jdk/java/nio/file/Path/Extensions.java deleted file mode 100644 index d6113210d05..00000000000 --- a/test/jdk/java/nio/file/Path/Extensions.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 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. - */ - -import java.nio.file.Path; - -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/* - * @test - * @bug 8057113 - * @summary Verify getExtension method - * @run testng Extensions - */ -public class Extensions { - /** - * Returns path name string and expected extension pairs. - * - * @return {@code {{"pathname", "extension"},...}} - */ - @DataProvider - static Object[][] getProvider() { - Object[][] pairs = { - {"", null}, - {".", null}, - {"..", ""}, - {"...", ""}, - {"....", ""}, - {".....", ""}, - {"aa", null}, - {"a.", ""}, - {".a", null}, - {"..a", "a"}, - {"...a", "a"}, - {"....a", "a"}, - {".a.b", "b"}, - {"...a.b", "b"}, - {"...a.b.", ""}, - {"..foo", "foo"}, - {"foo.", ""}, - {"test.", ""}, - {"test..", ""}, - {"test...", ""}, - {"test.rb", "rb"}, - {"a/b/d/test.rb" , "rb"}, - {".a/b/d/test.rb", "rb"}, - {"test", null}, - {".profile", null}, - {".profile.sh", "sh"}, - {"foo.tar.gz", "gz"}, - {"foo.bar.", ""}, - {"archive.zip", "zip"}, - {"compress.gzip", "gzip"}, - {"waitwhat.&$!#%", "&$!#%"}, - {"6.283185307", "283185307"} - }; - return pairs; - } - - @Test(dataProvider = "getProvider") - public static void get(String pathname, String extension) { - Assert.assertEquals(Path.of(pathname).getExtension(), extension); - } -} diff --git a/test/jdk/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java b/test/jdk/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java index d763b55c455..ed07225c58a 100644 --- a/test/jdk/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java +++ b/test/jdk/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4322806 + * @bug 4322806 8189338 * @summary When an RMI (JRMP) connection is made to a TCP address that is * listening, so the connection is accepted, but the server never responds * to the initial JRMP handshake (nor does it terminate the connection), @@ -38,8 +38,11 @@ * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp * @run main/othervm HandshakeTimeout + * @run main/othervm HandshakeTimeout SSL */ +import javax.rmi.ssl.SslRMIClientSocketFactory; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.rmi.ConnectException; import java.rmi.ConnectIOException; @@ -60,12 +63,19 @@ public static void main(String[] args) throws Exception { * Listen on port, but never process connections made to it. */ ServerSocket serverSocket = new ServerSocket(0); - int port = serverSocket.getLocalPort(); + InetSocketAddress address = (InetSocketAddress) serverSocket.getLocalSocketAddress(); /* * Attempt RMI call to port in separate thread. */ - Registry registry = LocateRegistry.getRegistry(port); + Registry registry; + if (args.length == 0) { + registry = LocateRegistry.getRegistry(address.getPort()); + } else { + registry = LocateRegistry.getRegistry(address.getHostString(), + address.getPort(), new SslRMIClientSocketFactory()); + } + Connector connector = new Connector(registry); Thread t = new Thread(connector); t.setDaemon(true); diff --git a/test/jdk/java/security/Policy/Root/Root.java b/test/jdk/java/security/Policy/Root/Root.java index 497156edcd9..bb339ee342c 100644 --- a/test/jdk/java/security/Policy/Root/Root.java +++ b/test/jdk/java/security/Policy/Root/Root.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -22,27 +22,46 @@ */ /* - * + * @test * @bug 4619757 * @summary User Policy Setting is not recognized on Netscape 6 * when invoked as root. - * @run main/manual Root + * @library /test/lib + * @run testng/othervm Root */ -/* - * Place Root.policy in the root home directory (/), - * as /.java.policy and run as test as root user. - */ +import org.testng.Assert; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.security.*; public class Root { - public static void main(String[] args) { + private static final String SRC = System.getProperty("test.src"); + private static final String ROOT = System.getProperty("user.home"); + private static final Path SOURCE = Paths.get(SRC, "Root.policy"); + private static final Path TARGET = Paths.get(ROOT, ".java.policy"); + + @BeforeTest + public void setup() throws IOException { + Files.copy(SOURCE, TARGET, StandardCopyOption.REPLACE_EXISTING); + } + + @AfterTest + public void cleanUp() throws IOException { + Files.delete(TARGET); + } + + @Test + private void test() { Policy p = Policy.getPolicy(); - if (p.implies(Root.class.getProtectionDomain(), new AllPermission())) { - System.out.println("Test succeeded"); - } else { - throw new SecurityException("Test failed"); - } + Assert.assertTrue(p.implies(Root.class.getProtectionDomain(), + new AllPermission())); } } diff --git a/test/jdk/java/security/SecureRandom/NoSync.java b/test/jdk/java/security/SecureRandom/NoSync.java index 032833c4a7f..3e8485313f3 100644 --- a/test/jdk/java/security/SecureRandom/NoSync.java +++ b/test/jdk/java/security/SecureRandom/NoSync.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -30,7 +30,7 @@ /* * @test * @bug 7004967 - * @run main/othervm NoSync + * @run main/othervm -Djava.security.egd=file:/dev/urandom NoSync * @summary SecureRandom should be more explicit about threading */ public class NoSync { diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java new file mode 100644 index 00000000000..69fe8effe70 --- /dev/null +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022, 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. + */ + +import jdk.test.lib.util.JarUtils; +import jdk.test.lib.SecurityTools; +import jdk.test.lib.Asserts; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.Calendar; +import java.util.Locale; +import java.util.List; +import java.util.ArrayList; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.nio.file.Files; +import java.io.File; +import static java.util.Calendar.WEDNESDAY; + +/* + * @test + * @bug 8297684 8269039 + * @summary Checking custom CalendarDataProvider with SPI contained in signed jar does + * not produce NPE. + * @modules java.base/sun.security.pkcs + * java.base/sun.security.timestamp + * java.base/sun.security.x509 + * java.base/sun.security.util + * java.base/sun.security.tools.keytool + * jdk.jartool/jdk.security.jarsigner + * @library /test/lib + * @library provider + * @build baz.CalendarDataProviderImpl + * @run main/timeout=600 TestSPISigned + */ +public class TestSPISigned { + + private static final String TEST_CLASSES = System.getProperty("test.classes", "."); + private static final String TEST_SRC = System.getProperty("test.src", "."); + + private static final Path META_INF_DIR = Paths.get(TEST_SRC, "provider", "meta"); + private static final Path PROVIDER_PARENT = Paths.get(TEST_CLASSES, ".."); + private static final Path PROVIDER_DIR = PROVIDER_PARENT.resolve("provider"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path UNSIGNED_JAR = MODS_DIR.resolve("unsigned-with-locale.jar"); + private static final Path SIGNED_JAR = MODS_DIR.resolve("signed-with-locale.jar"); + + public static void main(String[] args) throws Throwable { + if (args.length == 1) { + String arg = args[0]; + if ("run-test".equals(arg)) { + System.out.println("Debug: Running test"); + String provProp = System.getProperty("java.locale.providers"); + if (!"SPI".equals(provProp)) { + throw new RuntimeException("Test failed! Expected -Djava.locale.providers=SPI to be set for test run"); + } + doRunTest(); + } else { + throw new RuntimeException("Test failed! Expected 'run-test' arg for test run"); + } + } else { + // Set up signed jar with custom calendar data provider + // + // 1. Create jar with custom CalendarDataProvider + JarUtils.createJarFile(UNSIGNED_JAR, PROVIDER_DIR); + JarUtils.updateJarFile(UNSIGNED_JAR, META_INF_DIR); + // create signer's keypair + SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " + + "-storepass changeit -dname CN=test -alias test") + .shouldHaveExitValue(0); + // sign jar + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar " + SIGNED_JAR + " " + UNSIGNED_JAR + " test") + .shouldHaveExitValue(0); + // run test, which must not throw a NPE + List testRun = new ArrayList<>(); + testRun.add("-Djava.locale.providers=SPI"); + testRun.add("-cp"); + String classPath = System.getProperty("java.class.path"); + classPath = classPath + File.pathSeparator + SIGNED_JAR.toAbsolutePath().toString(); + testRun.add(classPath); + testRun.add(TestSPISigned.class.getSimpleName()); + testRun.add("run-test"); + OutputAnalyzer out = ProcessTools.executeTestJvm(testRun); + out.shouldHaveExitValue(0); + out.shouldContain("DEBUG: Getting xx language"); + } + } + + private static void doRunTest() { + Locale locale = new Locale("xx", "YY"); + Calendar kcal = Calendar.getInstance(locale); + try { + check(WEDNESDAY, kcal.getFirstDayOfWeek()); + check(7, kcal.getMinimalDaysInFirstWeek()); + } catch (Throwable ex) { + throw new RuntimeException("Test failed with signed jar and " + + " argument java.locale.providers=SPI", ex); + } + } + + private static void check(T expected, T actual) { + Asserts.assertEquals(expected, actual, "Expected calendar from SPI to be in effect"); + } + +} diff --git a/src/hotspot/share/metaprogramming/removeCV.hpp b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java similarity index 58% rename from src/hotspot/share/metaprogramming/removeCV.hpp rename to test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java index 5ddafc54746..958aa128e93 100644 --- a/src/hotspot/share/metaprogramming/removeCV.hpp +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -19,32 +19,32 @@ * 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_METAPROGRAMMING_REMOVECV_HPP -#define SHARE_METAPROGRAMMING_REMOVECV_HPP - -#include "memory/allStatic.hpp" +package baz; -template -struct RemoveCV: AllStatic { - typedef T type; -}; +import static java.util.Calendar.*; +import java.util.Locale; +import java.util.spi.CalendarDataProvider; -template -struct RemoveCV: AllStatic { - typedef T type; -}; +public class CalendarDataProviderImpl extends CalendarDataProvider { + private static final Locale[] locales = { new Locale("xx", "YY") }; -template -struct RemoveCV: AllStatic { - typedef T type; -}; + @Override + public int getFirstDayOfWeek(Locale locale) { + return WEDNESDAY; + } -template -struct RemoveCV: AllStatic { - typedef T type; -}; + @Override + public int getMinimalDaysInFirstWeek(Locale locale) { + if (locale.getLanguage().equals("xx")) { + System.out.println("DEBUG: Getting xx language"); + } + return 7; + } -#endif // SHARE_METAPROGRAMMING_REMOVECV_HPP + @Override + public Locale[] getAvailableLocales() { + return locales; + } +} diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider new file mode 100644 index 00000000000..1563e3b3086 --- /dev/null +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider @@ -0,0 +1,7 @@ +# +# +# +# fully-qualified name of the java.util.spi.CalendarDataProvider +# implementation class +# +baz.CalendarDataProviderImpl diff --git a/test/jdk/java/text/Format/NumberFormat/CurrencySymbols.properties b/test/jdk/java/text/Format/NumberFormat/CurrencySymbols.properties index cf73a9c7e31..9ee1ea52ca6 100644 --- a/test/jdk/java/text/Format/NumberFormat/CurrencySymbols.properties +++ b/test/jdk/java/text/Format/NumberFormat/CurrencySymbols.properties @@ -1,3 +1,26 @@ +# +# Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + ar=\u00A4 ar_AE=\u062F.\u0625.\u200F ar_BH=\u062F.\u0628.\u200F @@ -79,7 +102,7 @@ fr_FR=\u20AC fr_LU=\u20AC hi_IN=\u0930\u0942 hr=\u00A4 -hr_HR=Kn +hr_HR=\u20AC hu=\u00A4 hu_HU=Ft is=\u00A4 @@ -94,9 +117,9 @@ ja_JP=\uFFE5 ko=\u00A4 ko_KR=\uFFE6 lt=\u00A4 -lt_LT=Lt;2014-12-31-22-00-00;\u20AC +lt_LT=\u20AC lv=\u00A4 -lv_LV=Ls;2013-12-31-22-00-00;\u20AC +lv_LV=\u20AC mk=\u00A4 mk_MK=Den nl=\u00A4 diff --git a/test/jdk/java/time/test/java/time/zone/TestZoneRulesProvider.java b/test/jdk/java/time/test/java/time/zone/TestZoneRulesProvider.java new file mode 100644 index 00000000000..71f816842ce --- /dev/null +++ b/test/jdk/java/time/test/java/time/zone/TestZoneRulesProvider.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package test.java.time.zone; + +import java.time.ZoneId; +import java.time.zone.ZoneRules; +import java.time.zone.ZoneRulesException; +import java.time.zone.ZoneRulesProvider; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.NavigableMap; +import java.util.Set; + +import org.testng.annotations.Test; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * @summary Tests for ZoneRulesProvider class. + * @bug 8299571 + */ +@Test +public class TestZoneRulesProvider { + private static final Set MY_ZONE_IDS = + new LinkedHashSet(Arrays.asList(new String[] {"MyID_1", "MyID_2", "CET", "MyID_3"})); + + /** + * Tests whether partially registered zones are cleaned on a provider registration + * failure, in case a duplicated zone is detected. + */ + @Test + public void test_registerDuplicatedZone() { + try { + ZoneRulesProvider.registerProvider(new ZoneRulesProvider() { + @Override + protected Set provideZoneIds() { + return MY_ZONE_IDS; + } + + @Override + protected ZoneRules provideRules(String zoneId, boolean forCaching) { + return null; + } + + @Override + protected NavigableMap provideVersions(String zoneId) { + return null; + } + }); + throw new RuntimeException("Registering a provider that duplicates a zone should throw an exception"); + } catch (ZoneRulesException e) { + // Ignore. Failure on registration is expected. + } + + MY_ZONE_IDS.stream().forEach(id -> { + var isCET = id.equals("CET"); + + // availability check + var available = ZoneId.getAvailableZoneIds().contains(id); + if (available ^ isCET) { + throw new RuntimeException("Unexpected availability for " + id + ", availability: " + available); + } + + // instantiation check + try { + ZoneId.of(id); + assertTrue(isCET, "ZoneId.of() for the custom id %s should throw ZoneRulesException.".formatted(id)); + } catch (ZoneRulesException e) { + assertFalse(isCET, "Not possible to obtain a ZoneId for \"CET\"."); + } + }); + } +} diff --git a/test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java b/test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java index a310f968ded..c872d09ab5a 100644 --- a/test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java +++ b/test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ import java.util.Locale; import java.util.Map; -import static java.util.Calendar.*; import static java.util.GregorianCalendar.*; public class Symbol { diff --git a/test/jdk/java/util/Formatter/Padding.java b/test/jdk/java/util/Formatter/Padding.java new file mode 100644 index 00000000000..982b6967928 --- /dev/null +++ b/test/jdk/java/util/Formatter/Padding.java @@ -0,0 +1,313 @@ +/* + * 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 + * @bug 4906370 + * @summary Tests to excercise padding on int and double values, + * with various flag combinations. + * @run junit Padding + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +public class Padding { + + static Arguments[] padding() { + return new Arguments[] { + /* blank padding, right adjusted, optional plus sign */ + arguments("12", "%1d", 12), + arguments("12", "%2d", 12), + arguments(" 12", "%3d", 12), + arguments(" 12", "%4d", 12), + arguments(" 12", "%5d", 12), + arguments(" 12", "%10d", 12), + + arguments("-12", "%1d", -12), + arguments("-12", "%2d", -12), + arguments("-12", "%3d", -12), + arguments(" -12", "%4d", -12), + arguments(" -12", "%5d", -12), + arguments(" -12", "%10d", -12), + + arguments("1.2", "%1.1f", 1.2), + arguments("1.2", "%2.1f", 1.2), + arguments("1.2", "%3.1f", 1.2), + arguments(" 1.2", "%4.1f", 1.2), + arguments(" 1.2", "%5.1f", 1.2), + arguments(" 1.2", "%10.1f", 1.2), + + arguments("-1.2", "%1.1f", -1.2), + arguments("-1.2", "%2.1f", -1.2), + arguments("-1.2", "%3.1f", -1.2), + arguments("-1.2", "%4.1f", -1.2), + arguments(" -1.2", "%5.1f", -1.2), + arguments(" -1.2", "%10.1f", -1.2), + + /* blank padding, right adjusted, mandatory plus sign */ + arguments("+12", "%+1d", 12), + arguments("+12", "%+2d", 12), + arguments("+12", "%+3d", 12), + arguments(" +12", "%+4d", 12), + arguments(" +12", "%+5d", 12), + arguments(" +12", "%+10d", 12), + + arguments("-12", "%+1d", -12), + arguments("-12", "%+2d", -12), + arguments("-12", "%+3d", -12), + arguments(" -12", "%+4d", -12), + arguments(" -12", "%+5d", -12), + arguments(" -12", "%+10d", -12), + + arguments("+1.2", "%+1.1f", 1.2), + arguments("+1.2", "%+2.1f", 1.2), + arguments("+1.2", "%+3.1f", 1.2), + arguments("+1.2", "%+4.1f", 1.2), + arguments(" +1.2", "%+5.1f", 1.2), + arguments(" +1.2", "%+10.1f", 1.2), + + arguments("-1.2", "%+1.1f", -1.2), + arguments("-1.2", "%+2.1f", -1.2), + arguments("-1.2", "%+3.1f", -1.2), + arguments("-1.2", "%+4.1f", -1.2), + arguments(" -1.2", "%+5.1f", -1.2), + arguments(" -1.2", "%+10.1f", -1.2), + + /* blank padding, right adjusted, mandatory blank sign */ + arguments(" 12", "% 1d", 12), + arguments(" 12", "% 2d", 12), + arguments(" 12", "% 3d", 12), + arguments(" 12", "% 4d", 12), + arguments(" 12", "% 5d", 12), + arguments(" 12", "% 10d", 12), + + arguments("-12", "% 1d", -12), + arguments("-12", "% 2d", -12), + arguments("-12", "% 3d", -12), + arguments(" -12", "% 4d", -12), + arguments(" -12", "% 5d", -12), + arguments(" -12", "% 10d", -12), + + arguments(" 1.2", "% 1.1f", 1.2), + arguments(" 1.2", "% 2.1f", 1.2), + arguments(" 1.2", "% 3.1f", 1.2), + arguments(" 1.2", "% 4.1f", 1.2), + arguments(" 1.2", "% 5.1f", 1.2), + arguments(" 1.2", "% 10.1f", 1.2), + + arguments("-1.2", "% 1.1f", -1.2), + arguments("-1.2", "% 2.1f", -1.2), + arguments("-1.2", "% 3.1f", -1.2), + arguments("-1.2", "% 4.1f", -1.2), + arguments(" -1.2", "% 5.1f", -1.2), + arguments(" -1.2", "% 10.1f", -1.2), + + /* blank padding, left adjusted, optional sign */ + arguments("12", "%-1d", 12), + arguments("12", "%-2d", 12), + arguments("12 ", "%-3d", 12), + arguments("12 ", "%-4d", 12), + arguments("12 ", "%-5d", 12), + arguments("12 ", "%-10d", 12), + + arguments("-12", "%-1d", -12), + arguments("-12", "%-2d", -12), + arguments("-12", "%-3d", -12), + arguments("-12 ", "%-4d", -12), + arguments("-12 ", "%-5d", -12), + arguments("-12 ", "%-10d", -12), + + arguments("1.2", "%-1.1f", 1.2), + arguments("1.2", "%-2.1f", 1.2), + arguments("1.2", "%-3.1f", 1.2), + arguments("1.2 ", "%-4.1f", 1.2), + arguments("1.2 ", "%-5.1f", 1.2), + arguments("1.2 ", "%-10.1f", 1.2), + + arguments("-1.2", "%-1.1f", -1.2), + arguments("-1.2", "%-2.1f", -1.2), + arguments("-1.2", "%-3.1f", -1.2), + arguments("-1.2", "%-4.1f", -1.2), + arguments("-1.2 ", "%-5.1f", -1.2), + arguments("-1.2 ", "%-10.1f", -1.2), + + /* blank padding, left adjusted, mandatory plus sign */ + arguments("+12", "%-+1d", 12), + arguments("+12", "%-+2d", 12), + arguments("+12", "%-+3d", 12), + arguments("+12 ", "%-+4d", 12), + arguments("+12 ", "%-+5d", 12), + arguments("+12 ", "%-+10d", 12), + + arguments("-12", "%-+1d", -12), + arguments("-12", "%-+2d", -12), + arguments("-12", "%-+3d", -12), + arguments("-12 ", "%-+4d", -12), + arguments("-12 ", "%-+5d", -12), + arguments("-12 ", "%-+10d", -12), + + arguments("+1.2", "%-+1.1f", 1.2), + arguments("+1.2", "%-+2.1f", 1.2), + arguments("+1.2", "%-+3.1f", 1.2), + arguments("+1.2", "%-+4.1f", 1.2), + arguments("+1.2 ", "%-+5.1f", 1.2), + arguments("+1.2 ", "%-+10.1f", 1.2), + + arguments("-1.2", "%-+1.1f", -1.2), + arguments("-1.2", "%-+2.1f", -1.2), + arguments("-1.2", "%-+3.1f", -1.2), + arguments("-1.2", "%-+4.1f", -1.2), + arguments("-1.2 ", "%-+5.1f", -1.2), + arguments("-1.2 ", "%-+10.1f", -1.2), + + /* blank padding, left adjusted, mandatory blank sign */ + arguments(" 12", "%- 1d", 12), + arguments(" 12", "%- 2d", 12), + arguments(" 12", "%- 3d", 12), + arguments(" 12 ", "%- 4d", 12), + arguments(" 12 ", "%- 5d", 12), + arguments(" 12 ", "%- 10d", 12), + + arguments("-12", "%- 1d", -12), + arguments("-12", "%- 2d", -12), + arguments("-12", "%- 3d", -12), + arguments("-12 ", "%- 4d", -12), + arguments("-12 ", "%- 5d", -12), + arguments("-12 ", "%- 10d", -12), + + arguments(" 1.2", "%- 1.1f", 1.2), + arguments(" 1.2", "%- 2.1f", 1.2), + arguments(" 1.2", "%- 3.1f", 1.2), + arguments(" 1.2", "%- 4.1f", 1.2), + arguments(" 1.2 ", "%- 5.1f", 1.2), + arguments(" 1.2 ", "%- 10.1f", 1.2), + + arguments("-1.2", "%- 1.1f", -1.2), + arguments("-1.2", "%- 2.1f", -1.2), + arguments("-1.2", "%- 3.1f", -1.2), + arguments("-1.2", "%- 4.1f", -1.2), + arguments("-1.2 ", "%- 5.1f", -1.2), + arguments("-1.2 ", "%- 10.1f", -1.2), + + /* zero padding, right adjusted, optional sign */ + arguments("12", "%01d", 12), + arguments("12", "%02d", 12), + arguments("012", "%03d", 12), + arguments("0012", "%04d", 12), + arguments("00012", "%05d", 12), + arguments("0000000012", "%010d", 12), + + arguments("-12", "%01d", -12), + arguments("-12", "%02d", -12), + arguments("-12", "%03d", -12), + arguments("-012", "%04d", -12), + arguments("-0012", "%05d", -12), + arguments("-000000012", "%010d", -12), + + arguments("1.2", "%01.1f", 1.2), + arguments("1.2", "%02.1f", 1.2), + arguments("1.2", "%03.1f", 1.2), + arguments("01.2", "%04.1f", 1.2), + arguments("001.2", "%05.1f", 1.2), + arguments("00000001.2", "%010.1f", 1.2), + + arguments("-1.2", "%01.1f", -1.2), + arguments("-1.2", "%02.1f", -1.2), + arguments("-1.2", "%03.1f", -1.2), + arguments("-1.2", "%04.1f", -1.2), + arguments("-01.2", "%05.1f", -1.2), + arguments("-0000001.2", "%010.1f", -1.2), + + /* zero padding, right adjusted, mandatory plus sign */ + arguments("+12", "%+01d", 12), + arguments("+12", "%+02d", 12), + arguments("+12", "%+03d", 12), + arguments("+012", "%+04d", 12), + arguments("+0012", "%+05d", 12), + arguments("+000000012", "%+010d", 12), + + arguments("-12", "%+01d", -12), + arguments("-12", "%+02d", -12), + arguments("-12", "%+03d", -12), + arguments("-012", "%+04d", -12), + arguments("-0012", "%+05d", -12), + arguments("-000000012", "%+010d", -12), + + arguments("+1.2", "%+01.1f", 1.2), + arguments("+1.2", "%+02.1f", 1.2), + arguments("+1.2", "%+03.1f", 1.2), + arguments("+1.2", "%+04.1f", 1.2), + arguments("+01.2", "%+05.1f", 1.2), + arguments("+0000001.2", "%+010.1f", 1.2), + + arguments("-1.2", "%+01.1f", -1.2), + arguments("-1.2", "%+02.1f", -1.2), + arguments("-1.2", "%+03.1f", -1.2), + arguments("-1.2", "%+04.1f", -1.2), + arguments("-01.2", "%+05.1f", -1.2), + arguments("-0000001.2", "%+010.1f", -1.2), + + /* zero padding, right adjusted, mandatory blank sign */ + arguments(" 12", "% 01d", 12), + arguments(" 12", "% 02d", 12), + arguments(" 12", "% 03d", 12), + arguments(" 012", "% 04d", 12), + arguments(" 0012", "% 05d", 12), + arguments(" 000000012", "% 010d", 12), + + arguments("-12", "% 01d", -12), + arguments("-12", "% 02d", -12), + arguments("-12", "% 03d", -12), + arguments("-012", "% 04d", -12), + arguments("-0012", "% 05d", -12), + arguments("-000000012", "% 010d", -12), + + arguments(" 1.2", "% 01.1f", 1.2), + arguments(" 1.2", "% 02.1f", 1.2), + arguments(" 1.2", "% 03.1f", 1.2), + arguments(" 1.2", "% 04.1f", 1.2), + arguments(" 01.2", "% 05.1f", 1.2), + arguments(" 0000001.2", "% 010.1f", 1.2), + + arguments("-1.2", "% 01.1f", -1.2), + arguments("-1.2", "% 02.1f", -1.2), + arguments("-1.2", "% 03.1f", -1.2), + arguments("-1.2", "% 04.1f", -1.2), + arguments("-01.2", "% 05.1f", -1.2), + arguments("-0000001.2", "% 010.1f", -1.2), + + }; + } + + @ParameterizedTest + @MethodSource + void padding(String expected, String format, Object value) { + assertEquals(expected, String.format(format, value)); + } + +} diff --git a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java index 234f6fdba7b..28afa8f49e1 100644 --- a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java +++ b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java @@ -33,32 +33,48 @@ import java.util.Date; import java.util.List; import java.util.SimpleTimeZone; +import java.util.TimeZone; import java.time.DayOfWeek; import java.time.ZonedDateTime; import java.time.temporal.TemporalAdjusters; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; public class CustomTzIDCheckDST { - private static String CUSTOM_TZ = "MEZ-1MESZ,M3.5.0,M10.5.0"; + // Northern Hemisphere + private static String CUSTOM_TZ = "MEZ-1MESZ,M3.5.0,M10.5.0/3"; + // Simulate Southern Hemisphere + private static String CUSTOM_TZ2 = "MEZ-1MESZ,M10.5.0,M3.5.0/3"; public static void main(String args[]) throws Throwable { if (args.length == 0) { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(List.of("CustomTzIDCheckDST", "runTZTest")); pb.environment().put("TZ", CUSTOM_TZ); OutputAnalyzer output = ProcessTools.executeProcess(pb); output.shouldHaveExitValue(0); + pb.environment().put("TZ", CUSTOM_TZ2); + output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); } else { runTZTest(); } } - /* TZ code will always be set to "MEZ-1MESZ,M3.5.0,M10.5.0". + /* TZ is set to "MEZ-1MESZ,M3.5.0,M10.5.0/3", it will be the northern hemisphere. * This ensures the transition periods for Daylights Savings should be at March's last * Sunday and October's last Sunday. */ private static void runTZTest() { Date time = new Date(); - if (new SimpleTimeZone(3600000, "MEZ-1MESZ", Calendar.MARCH, -1, Calendar.SUNDAY, 0, - Calendar.OCTOBER, -1, Calendar.SUNDAY, 0).inDaylightTime(time)) { + String tzStr = System.getenv("TZ"); + if (tzStr == null) + throw new RuntimeException("Got unexpected timezone information: TZ is null"); + boolean nor = CUSTOM_TZ.equals(tzStr); + TimeZone tz = new SimpleTimeZone(3600000, tzStr, + nor ? Calendar.MARCH : Calendar.OCTOBER, -1, + Calendar.SUNDAY, 3600000, SimpleTimeZone.UTC_TIME, + nor ? Calendar.OCTOBER : Calendar.MARCH, -1, + Calendar.SUNDAY, 3600000, SimpleTimeZone.UTC_TIME, + 3600000); + if (tz.inDaylightTime(time)) { // We are in Daylight savings period. if (time.toString().endsWith("GMT+02:00 " + Integer.toString(time.getYear() + 1900))) return; @@ -68,7 +84,7 @@ private static void runTZTest() { } // Reaching here means time zone did not match up as expected. - throw new RuntimeException("Got unexpected timezone information: " + time); + throw new RuntimeException("Got unexpected timezone information: " + tzStr + " " + time); } private static ZonedDateTime getLastSundayOfMonth(ZonedDateTime date) { diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION index f29d2d938b1..0f66ee12c94 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION @@ -1 +1 @@ -tzdata2022f +tzdata2022g diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt index 24cec5af700..d495743b268 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt +++ b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt @@ -204,6 +204,7 @@ Link America/Tijuana America/Ensenada Link America/Indiana/Indianapolis America/Fort_Wayne Link America/Toronto America/Montreal Link America/Toronto America/Nipigon +Link America/Iqaluit America/Pangnirtung Link America/Rio_Branco America/Porto_Acre Link America/Winnipeg America/Rainy_River Link America/Argentina/Cordoba America/Rosario diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt b/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt index a1cd41d283d..44db4dbdb81 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt +++ b/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt @@ -25,6 +25,7 @@ America/Cambridge_Bay MST MDT America/Cancun EST America/Chicago CST CDT America/Chihuahua CST +America/Ciudad_Juarez MST MDT America/Costa_Rica CST CDT America/Danmarkshavn GMT America/Dawson MST @@ -71,9 +72,8 @@ America/Nome AKST AKDT America/North_Dakota/Beulah CST CDT America/North_Dakota/Center CST CDT America/North_Dakota/New_Salem CST CDT -America/Ojinaga CST +America/Ojinaga CST CDT America/Panama EST -America/Pangnirtung EST EDT America/Phoenix MST America/Port-au-Prince EST EDT America/Puerto_Rico AST diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java new file mode 100644 index 00000000000..b35ab064d53 --- /dev/null +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java @@ -0,0 +1,219 @@ +/* + * 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 is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.LockSupport; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Tests for ForkJoinPool and ForkJoinWorkerThread additions in JDK 20. + */ +public class ForkJoinPool20Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinPool20Test.class); + } + + /** + * Test that tasks submitted with externalSubmit execute. + */ + public void testExternalSubmit1() throws Exception { + try (var pool = new ForkJoinPool()) { + // submit from external client + var task1 = ForkJoinTask.adapt(() -> "foo"); + pool.externalSubmit(task1); + assertEquals(task1.get(), "foo"); + + // submit from worker thread + Future> task2 = pool.submit(() -> { + return pool.externalSubmit(ForkJoinTask.adapt(() -> "foo")); + }); + assertEquals(task2.get().get(), "foo"); + } + } + + /** + * Test that tasks submitted with externalSubmit are pushed to a submission queue. + */ + public void testExternalSubmit2() throws Exception { + try (var pool = new ForkJoinPool(1)) { + pool.submit(() -> { + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == 0); + + for (int count = 1; count <= 3; count++) { + var task = ForkJoinTask.adapt(() -> { }); + pool.externalSubmit(task); + + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == count); + } + }).get(); + } + } + + /** + * Test externalSubmit return value. + */ + public void testExternalSubmitReturnsTask() { + try (var pool = new ForkJoinPool()) { + var task = ForkJoinTask.adapt(() -> "foo"); + assertTrue(pool.externalSubmit(task) == task); + } + } + + /** + * Test externalSubmit(null) throws NullPointerException. + */ + public void testExternalSubmitWithNull() { + try (var pool = new ForkJoinPool()) { + assertThrows(NullPointerException.class, () -> pool.externalSubmit(null)); + } + } + + /** + * Test externalSubmit throws RejectedExecutionException when pool is shutdown. + */ + public void testExternalSubmitWhenShutdown() { + try (var pool = new ForkJoinPool()) { + pool.shutdown(); + var task = ForkJoinTask.adapt(() -> { }); + assertThrows(RejectedExecutionException.class, () -> pool.externalSubmit(task)); + } + } + + /** + * Test that tasks submitted with submit(ForkJoinTask) are pushed to a + * submission queue. + */ + public void testSubmit() throws Exception { + try (var pool = new ForkJoinPool(1)) { + ForkJoinWorkerThread worker = submitBusyTask(pool); + try { + assertTrue(worker.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == 0); + + for (int count = 1; count <= 3; count++) { + var task = ForkJoinTask.adapt(() -> { }); + pool.submit(task); + + // task should be in submission queue + assertTrue(worker.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == count); + } + } finally { + LockSupport.unpark(worker); + } + } + } + + /** + * Test ForkJoinWorkerThread::getQueuedTaskCount returns the number of tasks in the + * current thread's queue. This test runs with parallelism of 1 to ensure that tasks + * aren't stolen. + */ + public void testGetQueuedTaskCount1() throws Exception { + try (var pool = new ForkJoinPool(1)) { + pool.submit(() -> { + var worker = (ForkJoinWorkerThread) Thread.currentThread(); + assertTrue(worker.getQueuedTaskCount() == 0); + + for (int count = 1; count <= 3; count++) { + pool.submit(() -> { }); + + // task should be in this thread's task queue + assertTrue(worker.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedSubmissionCount() == 0); + } + }).get(); + } + } + + /** + * Test ForkJoinWorkerThread::getQueuedTaskCount returns the number of tasks in the + * thread's queue. This test runs with parallelism of 2 and one worker active running + * a task. This gives the test two task queues to sample. + */ + public void testGetQueuedTaskCount2() throws Exception { + try (var pool = new ForkJoinPool(2)) { + // keep one worker thread active + ForkJoinWorkerThread worker1 = submitBusyTask(pool); + try { + pool.submit(() -> { + var worker2 = (ForkJoinWorkerThread) Thread.currentThread(); + for (int count = 1; count <= 3; count++) { + pool.submit(() -> { }); + + // task should be in this thread's task queue + assertTrue(worker1.getQueuedTaskCount() == 0); + assertTrue(worker2.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedSubmissionCount() == 0); + } + }).get(); + } finally { + LockSupport.unpark(worker1); // release worker1 + } + } + } + + /** + * Submits a task to the pool, returning the worker thread that runs the + * task. The task runs until the thread is unparked. + */ + static ForkJoinWorkerThread submitBusyTask(ForkJoinPool pool) throws Exception { + var ref = new AtomicReference(); + pool.submit(() -> { + ref.set((ForkJoinWorkerThread) Thread.currentThread()); + LockSupport.park(); + }); + ForkJoinWorkerThread worker; + while ((worker = ref.get()) == null) { + Thread.sleep(20); + } + return worker; + } +} diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java index 427ec44cf5f..a5d491f6ce0 100644 --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java @@ -513,7 +513,8 @@ public String run() { public static boolean atLeastJava14() { return JAVA_CLASS_VERSION >= 58.0; } public static boolean atLeastJava15() { return JAVA_CLASS_VERSION >= 59.0; } public static boolean atLeastJava16() { return JAVA_CLASS_VERSION >= 60.0; } - public static boolean atLeastJava17() { return JAVA_CLASS_VERSION >= 61.0; } + public static boolean atLeastJava19() { return JAVA_CLASS_VERSION >= 63.0; } + public static boolean atLeastJava20() { return JAVA_CLASS_VERSION >= 64.0; } /** * Collects all JSR166 unit tests as one suite. @@ -633,12 +634,20 @@ public static Test suite() { addNamedTestClasses(suite, java9TestClassNames); } - if (atLeastJava17()) { - String[] java17TestClassNames = { + if (atLeastJava19()) { + String[] java19TestClassNames = { "ForkJoinPool19Test", }; - addNamedTestClasses(suite, java17TestClassNames); + addNamedTestClasses(suite, java19TestClassNames); } + + if (atLeastJava20()) { + String[] java20TestClassNames = { + "ForkJoinPool20Test", + }; + addNamedTestClasses(suite, java20TestClassNames); + } + return suite; } diff --git a/test/jdk/java/util/regex/NegativeArraySize.java b/test/jdk/java/util/regex/NegativeArraySize.java index d64f6acb000..727f1b11fc3 100644 --- a/test/jdk/java/util/regex/NegativeArraySize.java +++ b/test/jdk/java/util/regex/NegativeArraySize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,7 +25,7 @@ * @test * @bug 8223174 * @summary Pattern.compile() can throw confusing NegativeArraySizeException - * @requires os.maxMemory >= 5g & vm.bits == 64 + * @requires os.maxMemory >= 6g & vm.bits == 64 & !vm.musl * @run testng/othervm -Xms5G -Xmx5G NegativeArraySize */ diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java index 1e8ddae42bb..efe69ef3c36 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java @@ -22,8 +22,8 @@ */ package org.openjdk.tests.java.util.stream; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import org.testng.annotations.Test; @@ -65,8 +65,8 @@ public void testDoubleSpliterator(String name, Supplier su @Test(dataProvider = "SegmentSpliterator", dataProviderClass = SegmentTestDataProvider.class ) public void testSegmentSpliterator(String name, SequenceLayout layout, SpliteratorTestHelper.ContentAsserter contentAsserter) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(layout); SegmentTestDataProvider.initSegment(segment); SpliteratorTestHelper.testSpliterator(() -> segment.spliterator(layout), SegmentTestDataProvider::segmentCopier, contentAsserter); diff --git a/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java b/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java index e501436f736..92843e819c6 100644 --- a/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java +++ b/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java @@ -23,57 +23,74 @@ * questions. */ -/** +/* * @test * @bug 8286779 * @summary Test limited/default_local.policy containing inconsistent entries - * @run main/manual InconsistentEntries + * @library /test/lib + * @run testng/othervm InconsistentEntries */ + +import org.testng.Assert; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + import javax.crypto.*; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.security.Security; public class InconsistentEntries { - public static void main(String[] args) throws Exception { - System.out.println("***********************************************************"); - System.out.println("// This is a manual test to test a custom \"default_local.policy\" containing inconsistent entries"); - System.out.println("// under a new subfolder \"$JAVA_HOME/conf/security/policy\" directory."); - System.out.println("// This test fails when the policy directory \"testlimited\" or the policy \"default_local.policy"); - System.out.println("// does not exist or is empty."); - System.out.println("// - Create a new subfolder \"testlimited\" under \"$JAVA_HOME/conf/security/policy\""); - System.out.println("// - Place the custom \"default_local.policy\" under \"testlimited\" directory"); - System.out.println("// - default_local.policy contains:"); - System.out.println("// grant {"); - System.out.println("// permission javax.crypto.CryptoAllPermission;"); - System.out.println("// permission javax.crypto.CryptoPermission \"DES\", 64;"); - System.out.println("// };"); - System.out.println("***********************************************************"); + private static final String JDK_HOME = System.getProperty("test.jdk"); + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path POLICY_DIR = Paths.get(JDK_HOME, "conf", "security", + "policy", "testlimited"); + private static final Path POLICY_FILE = Paths.get(TEST_SRC, "default_local.policy"); + + Path targetFile = null; + + @BeforeTest + public void setUp() throws IOException { + if (!POLICY_DIR.toFile().exists()) { + Files.createDirectory(POLICY_DIR); + } + targetFile = POLICY_DIR.resolve(POLICY_FILE.getFileName()); + Files.copy(POLICY_FILE, targetFile, StandardCopyOption.REPLACE_EXISTING); + } + + @AfterTest + public void cleanUp() throws IOException { + Files.delete(targetFile); + } + + @Test + public void test() throws Exception { String JAVA_HOME = System.getProperty("java.home"); String FS = System.getProperty("file.separator"); Path testlimited = Path.of(JAVA_HOME + FS + "conf" + FS + "security" + FS + "policy" + FS + "testlimited"); if (!Files.exists(testlimited)) { - throw new RuntimeException("custom policy subdirectory: testlimited does not exist"); + throw new RuntimeException( + "custom policy subdirectory: testlimited does not exist"); } File testpolicy = new File(JAVA_HOME + FS + "conf" + FS + "security" + FS + "policy" + FS + "testlimited" + FS + "default_local.policy"); if (testpolicy.length() == 0) { - throw new RuntimeException("policy: default_local.policy does not exist or is empty"); + throw new RuntimeException( + "policy: default_local.policy does not exist or is empty"); } Security.setProperty("crypto.policy", "testlimited"); - try { - int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); - throw new RuntimeException("Should fail due to inconsistent entries in policy file"); - } catch (ExceptionInInitializerError e) { - e.printStackTrace(); - System.out.println("Test completed successfully"); - } + Assert.assertThrows(ExceptionInInitializerError.class, + () -> Cipher.getMaxAllowedKeyLength("AES")); } } diff --git a/test/jdk/javax/crypto/CryptoPermissions/default_local.policy b/test/jdk/javax/crypto/CryptoPermissions/default_local.policy new file mode 100644 index 00000000000..06f5911ded0 --- /dev/null +++ b/test/jdk/javax/crypto/CryptoPermissions/default_local.policy @@ -0,0 +1,4 @@ +grant { + permission javax.crypto.CryptoAllPermission; + permission javax.crypto.CryptoPermission "DES", 64; +} diff --git a/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh b/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh index feafda7bf25..0e66b03d3d3 100644 --- a/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh +++ b/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh @@ -22,7 +22,7 @@ # @test # @bug 6291034 # @run shell DeleteOnExitTest.sh -# @summary Verify that temporary imageio files files are deleted on VM exit. +# @summary Verify that temporary imageio files are deleted on VM exit. if [ -z "${TESTSRC}" ]; then echo "TESTSRC undefined: defaulting to ." diff --git a/test/jdk/javax/management/Introspector/ClassLeakTest.java b/test/jdk/javax/management/Introspector/ClassLeakTest.java index 9a08c04b0c2..f6316f7e2c3 100644 --- a/test/jdk/javax/management/Introspector/ClassLeakTest.java +++ b/test/jdk/javax/management/Introspector/ClassLeakTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -56,6 +56,7 @@ public static void main(String[] args) throws Exception { urls[i] = Paths.get(cpaths[i]).toUri().toURL(); } + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMBean.class.getName()); if (shadowClass == TestMBean.class) { diff --git a/test/jdk/javax/management/MBeanServer/PostExceptionTest.java b/test/jdk/javax/management/MBeanServer/PostExceptionTest.java index 3e3c802fc88..a004acceee5 100644 --- a/test/jdk/javax/management/MBeanServer/PostExceptionTest.java +++ b/test/jdk/javax/management/MBeanServer/PostExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -432,6 +432,7 @@ public ObjectName registerMLet(MBeanServer server) throws Exception { if (server.isRegistered(name)) { return name; } + @SuppressWarnings("removal") final MLet mlet = new MLet(new URL[0], ClassLoader.getSystemClassLoader()); return server.registerMBean(mlet, name).getObjectName(); diff --git a/test/jdk/javax/management/loading/DocumentRootTest.java b/test/jdk/javax/management/loading/DocumentRootTest.java index ae598ddd99e..73b1654d135 100644 --- a/test/jdk/javax/management/loading/DocumentRootTest.java +++ b/test/jdk/javax/management/loading/DocumentRootTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -38,6 +38,7 @@ import java.util.HashMap; import javax.management.loading.MLetContent; +@SuppressWarnings("removal") public class DocumentRootTest { public static int test(URL documentBase, URL codeBase) { int error = 0; diff --git a/test/jdk/javax/management/loading/GetMBeansFromURLTest.java b/test/jdk/javax/management/loading/GetMBeansFromURLTest.java index 5f4d889c91b..31b86c72e8d 100644 --- a/test/jdk/javax/management/loading/GetMBeansFromURLTest.java +++ b/test/jdk/javax/management/loading/GetMBeansFromURLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -40,6 +40,7 @@ import javax.management.ServiceNotFoundException; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class GetMBeansFromURLTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java b/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java index 2519f4329b2..2973b15c2cb 100644 --- a/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java +++ b/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,6 +39,7 @@ import javax.management.ObjectName; import java.io.File; +@SuppressWarnings("removal") public class MLetCommand { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/MLetContentTest.java b/test/jdk/javax/management/loading/MLetContentTest.java index 0fa9ce939f7..455a20533be 100644 --- a/test/jdk/javax/management/loading/MLetContentTest.java +++ b/test/jdk/javax/management/loading/MLetContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -37,6 +37,7 @@ import javax.management.loading.*; +@SuppressWarnings("removal") public class MLetContentTest { public static void main(String[] args) throws Exception { System.out.println(">>> General test for the public class MLetContent."); diff --git a/test/jdk/javax/management/loading/MLetInternalsTest.java b/test/jdk/javax/management/loading/MLetInternalsTest.java index 4d312728dcf..2007e68fddc 100644 --- a/test/jdk/javax/management/loading/MLetInternalsTest.java +++ b/test/jdk/javax/management/loading/MLetInternalsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -39,6 +39,7 @@ * @modules java.management/javax.management.loading:open * @run testng MLetInternalsTest */ +@SuppressWarnings("removal") public class MLetInternalsTest { private final static String CONSTRUCT_PARAMETER = "constructParameter"; diff --git a/test/jdk/javax/management/loading/MletParserLocaleTest.java b/test/jdk/javax/management/loading/MletParserLocaleTest.java index 065fd45d854..4242caad0a2 100644 --- a/test/jdk/javax/management/loading/MletParserLocaleTest.java +++ b/test/jdk/javax/management/loading/MletParserLocaleTest.java @@ -39,6 +39,7 @@ import javax.management.ObjectName; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class MletParserLocaleTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java b/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java index f02455826b4..4881d75556c 100644 --- a/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java +++ b/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -45,6 +45,7 @@ import javax.management.ServiceNotFoundException; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class ParserInfiniteLoopTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java b/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java index 3a02ea262b5..a677133ea50 100644 --- a/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -81,6 +81,7 @@ public void run(Map args) { + ".class", ""); URL[] urls = new URL[]{new URL(clsLoadPath)}; + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMXBean.class.getName()); @@ -266,6 +267,7 @@ public void run(Map args) { mbs.unregisterMBean(testName); mbs.unregisterMBean(mletName); + @SuppressWarnings("removal") WeakReference mletRef = new WeakReference(mlet); mlet = null; diff --git a/test/jdk/javax/management/relation/NonArrayListTest.java b/test/jdk/javax/management/relation/NonArrayListTest.java index 0304c198333..0bb75f7ca8a 100644 --- a/test/jdk/javax/management/relation/NonArrayListTest.java +++ b/test/jdk/javax/management/relation/NonArrayListTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -38,6 +38,8 @@ import javax.management.loading.MLet; public class NonArrayListTest { + + @SuppressWarnings("removal") // use of MLet public static void main(String[] args) throws Exception { MBeanServer mbs = MBeanServerFactory.createMBeanServer(); RelationService rs = new RelationService(true); diff --git a/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java b/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java index 9d949995351..1908a31e2de 100644 --- a/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java +++ b/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -101,6 +101,7 @@ public static void main(String[] args) throws Exception { URLClassLoader jrcl = (URLClassLoader) jmxRemoteClassLoader; URL[] urls = jrcl.getURLs(); + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(JMXServiceURL.class.getName()); if (shadowClass == JMXServiceURL.class) { diff --git a/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java b/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java index bf8c1639486..6d21127bf25 100644 --- a/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java +++ b/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -80,6 +80,7 @@ public static void main(String[] args) { } } + @SuppressWarnings("removal") // use of MLet private static boolean test() throws Exception { MBeanServer mbs = MBeanServerFactory.createMBeanServer(); diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java new file mode 100644 index 00000000000..e9165fa391c --- /dev/null +++ b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8281236 + * @summary Check DTLS connection behaviors for named groups configuration + * @modules java.base/sun.security.util + * @library /test/lib + * @build DTLSOverDatagram + * @run main/othervm DTLSNamedGroups + */ + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.security.Security; + +/** + * Test DTLS client authentication. + */ +public class DTLSNamedGroups extends DTLSOverDatagram { + // Make sure default DH(E) key exchange is not used for DTLS v1.2. + private static String[] cipherSuites = new String[] { + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + }; + + private final String[] serverNamedGroups; + private final String[] clientNamedGroups; + + public DTLSNamedGroups(String[] serverNamedGroups, + String[] clientNamedGroups) { + this.serverNamedGroups = serverNamedGroups; + this.clientNamedGroups = clientNamedGroups; + } + + @Override + SSLEngine createSSLEngine(boolean isClient) throws Exception { + SSLEngine engine = super.createSSLEngine(isClient); + + SSLParameters sslParameters = engine.getSSLParameters(); + if (isClient) { + sslParameters.setNamedGroups(clientNamedGroups); + sslParameters.setCipherSuites(cipherSuites); + } else { + sslParameters.setNamedGroups(serverNamedGroups); + } + engine.setSSLParameters(sslParameters); + + return engine; + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + runTest(new String[] { + "x25519", + "secp256r1" + }, + new String[] { + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + new String[] { + "secp256r1" + }, + false); + runTest(null, + new String[] { + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + null, + false); + runTest(new String[0], + new String[] { + "secp256r1" + }, + true); + runTest(new String[] { + "secp256r1" + }, + new String[0], + true); + runTest(new String[] { + "secp256NA" + }, + new String[] { + "secp256r1" + }, + true); + } + + private static void runTest(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) throws Exception { + DTLSNamedGroups testCase = new DTLSNamedGroups( + serverNamedGroups, clientNamedGroups); + try { + testCase.runTest(testCase); + } catch (Exception e) { + if (!exceptionExpected) { + throw e; + } else { // Otherwise, swallow the expected exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + } +} + diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java index 0118bcb3810..1820dbe5423 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -33,6 +33,7 @@ * @run main/othervm DTLSOverDatagram */ +import java.io.IOException; import java.nio.*; import java.net.*; import java.util.*; @@ -42,6 +43,7 @@ import jdk.test.lib.security.SSLContextBuilder; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; import jdk.test.lib.hexdump.HexPrinter; @@ -50,8 +52,6 @@ */ public class DTLSOverDatagram { - private static final int MAX_HANDSHAKE_LOOPS = 200; - private static final int MAX_APP_READ_LOOPS = 60; private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis private static final int BUFFER_SIZE = 1024; private static final int MAXIMUM_PACKET_SIZE = 1024; @@ -75,8 +75,9 @@ public class DTLSOverDatagram { private static final ByteBuffer CLIENT_APP = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); - private static Exception clientException = null; - private static Exception serverException = null; + private final AtomicBoolean exceptionOccurred = new AtomicBoolean(false); + + private final CountDownLatch serverStarted = new CountDownLatch(1); /* * ============================================================= * The test case @@ -148,18 +149,12 @@ void handshake(SSLEngine engine, DatagramSocket socket, SocketAddress peerAddr, String side) throws Exception { boolean endLoops = false; - int loops = MAX_HANDSHAKE_LOOPS; + int loops = 0; engine.beginHandshake(); - while (!endLoops && - (serverException == null) && (clientException == null)) { - - if (--loops < 0) { - throw new RuntimeException( - "Too many loops to produce handshake packets"); - } + while (!endLoops && !exceptionOccurred.get()) { SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); - log(side, "=======handshake(" + loops + ", " + hs + ")======="); + log(side, "=======handshake(" + ++loops + ", " + hs + ")======="); switch (hs) { case NEED_UNWRAP, NEED_UNWRAP_AGAIN -> { @@ -313,16 +308,10 @@ void deliverAppData(SSLEngine engine, DatagramSocket socket, void receiveAppData(SSLEngine engine, DatagramSocket socket, ByteBuffer expectedApp) throws Exception { - int loops = MAX_APP_READ_LOOPS; - while ((serverException == null) && (clientException == null)) { - if (--loops < 0) { - throw new RuntimeException( - "Too much loops to receive application data"); - } - + while (!exceptionOccurred.get()) { byte[] buf = new byte[BUFFER_SIZE]; - DatagramPacket packet = new DatagramPacket(buf, buf.length); - socket.receive(packet); + DatagramPacket packet = readFromSocket(socket, buf); + ByteBuffer netBuffer = ByteBuffer.wrap(buf, 0, packet.getLength()); ByteBuffer recBuffer = ByteBuffer.allocate(BUFFER_SIZE); SSLEngineResult rs = engine.unwrap(netBuffer, recBuffer); @@ -338,19 +327,31 @@ void receiveAppData(SSLEngine engine, } } + /* + Some tests failed with receive time-out errors when the client tried to read + from the server. The server thread had exited normally so the read _should_ + succeed. So let's try to read a couple of times before giving up. + */ + DatagramPacket readFromSocket(DatagramSocket socket, byte[] buffer) throws IOException { + for (int i = 1 ; i <= 2 ; ++i) { + try { + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + socket.receive(packet); + return packet; + } catch (SocketTimeoutException exc) { + System.out.println("Attempt " + i + ": Timeout occurred reading from socket."); + } + } + throw new IOException("Did not receive data after 2 attempts."); + } + // produce handshake packets boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, String side, List packets) throws Exception { boolean endLoops = false; - int loops = MAX_HANDSHAKE_LOOPS / 2; - while (!endLoops && - (serverException == null) && (clientException == null)) { - - if (--loops < 0) { - throw new RuntimeException( - "Too many loops to produce handshake packets"); - } + int loops = 0; + while (!endLoops && !exceptionOccurred.get()) { ByteBuffer oNet = ByteBuffer.allocate(32768); ByteBuffer oApp = ByteBuffer.allocate(0); @@ -360,7 +361,7 @@ boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, SSLEngineResult.Status rs = r.getStatus(); SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus(); log(side, "----produce handshake packet(" + - loops + ", " + rs + ", " + hs + ")----"); + ++loops + ", " + rs + ", " + hs + ")----"); verifySSLEngineResultStatus(r, side); @@ -518,10 +519,6 @@ SSLContext getDTLSContext() throws Exception { * The remainder is support stuff to kickstart the testing. */ - // Will the handshaking and application data exchange succeed? - public boolean isGoodJob() { - return true; - } public final void runTest(DTLSOverDatagram testCase) throws Exception { InetSocketAddress serverSocketAddress = new InetSocketAddress @@ -541,97 +538,51 @@ public final void runTest(DTLSOverDatagram testCase) throws Exception { InetSocketAddress clientSocketAddr = new InetSocketAddress( InetAddress.getLoopbackAddress(), clientSocket.getLocalPort()); - ExecutorService pool = Executors.newFixedThreadPool(2); - Future server, client; + ExecutorService pool = Executors.newFixedThreadPool(1); + Future server; - try { - server = pool.submit(new ServerCallable( + server = pool.submit(() -> runServer( testCase, serverSocket, clientSocketAddr)); - client = pool.submit(new ClientCallable( - testCase, clientSocket, serverSocketAddr)); - } finally { - pool.shutdown(); - } - - boolean failed = false; + pool.shutdown(); - // wait for client to finish - try { - System.out.println("Client finished: " + client.get()); - } catch (CancellationException | InterruptedException - | ExecutionException e) { - System.out.println("Exception on client side: "); - e.printStackTrace(System.out); - failed = true; - } - - // wait for server to finish - try { - System.out.println("Client finished: " + server.get()); - } catch (CancellationException | InterruptedException - | ExecutionException e) { - System.out.println("Exception on server side: "); - e.printStackTrace(System.out); - failed = true; - } - - if (failed) { - throw new RuntimeException("Test failed"); - } + runClient(testCase, clientSocket, serverSocketAddr); + server.get(); } } - record ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket, - InetSocketAddress clientSocketAddr) implements Callable { + Void runServer(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress clientSocketAddr) throws Exception { + try { + serverStarted.countDown(); + testCase.doServerSide(socket, clientSocketAddr); - @Override - public String call() throws Exception { - try { - testCase.doServerSide(socket, clientSocketAddr); - } catch (Exception e) { - System.out.println("Exception in ServerCallable.call():"); - e.printStackTrace(System.out); - serverException = e; - - if (testCase.isGoodJob()) { - throw e; - } else { - return "Well done, server!"; - } - } + } catch (Exception exc) { + exceptionOccurred.set(true); - if (testCase.isGoodJob()) { - return "Well done, server!"; - } else { - throw new Exception("No expected exception"); - } + // log for debugging clarity + System.out.println("Unexpected exception in server"); + exc.printStackTrace(System.err); + throw exc; } + + return null; } - record ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket, - InetSocketAddress serverSocketAddr) implements Callable { + private void runClient(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress serverSocketAddr) throws Exception { + if(!serverStarted.await(5, TimeUnit.SECONDS)) { + throw new Exception("Server did not start within 5 seconds."); + } - @Override - public String call() throws Exception { - try { - testCase.doClientSide(socket, serverSocketAddr); - } catch (Exception e) { - System.out.println("Exception in ClientCallable.call():"); - e.printStackTrace(System.out); - clientException = e; - - if (testCase.isGoodJob()) { - throw e; - } else { - return "Well done, client!"; - } - } + try { + testCase.doClientSide(socket, serverSocketAddr); + } catch (Exception exc) { + exceptionOccurred.set(true); - if (testCase.isGoodJob()) { - return "Well done, client!"; - } else { - throw new Exception("No expected exception"); - } + // log for debugging clarity + System.out.println("Unexpected exception in client."); + exc.printStackTrace(System.err); + throw exc; } } diff --git a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java index af5bdc36134..304cb0695d6 100644 --- a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java +++ b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -36,27 +36,32 @@ import java.net.DatagramPacket; import java.net.SocketAddress; +import java.util.concurrent.atomic.AtomicBoolean; /** - * Test that if handshake messages are crasged, the handshake would fail + * Test that if handshake messages are changed, the handshake would fail * because of handshaking hash verification. */ public class InvalidRecords extends DTLSOverDatagram { - boolean needInvalidRecords = true; + private static final AtomicBoolean needInvalidRecords = new AtomicBoolean(true); public static void main(String[] args) throws Exception { InvalidRecords testCase = new InvalidRecords(); testCase.runTest(testCase); - } - @Override - public boolean isGoodJob() { - return false; + if (needInvalidRecords.get()) { + // if this is true, the createHandshakePacket() method + // was NOT called twice to create ClientHello messages + throw new RuntimeException( + "The invalid handshake packet was not" + + " rejected as it should have been."); + } } + @Override DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { - if ((ba.length >= 60) && + if (needInvalidRecords.get() && (ba.length >= 60) && (ba[0x00] == (byte)0x16) && (ba[0x0D] == (byte)0x01) && (ba[0x3B] == (byte)0x00) && (ba[0x3C] > 0)) { @@ -65,18 +70,8 @@ DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { // ba[0x3B]: length of session ID // ba[0x3C]: length of cookie - if (!needInvalidRecords) { - // The 2nd ClientHello with cookie. The 1st one should be - // rejected as expected. - // - // This may happen if the last few bytes of the packet are - // for supported_version extension. - throw new RuntimeException( - "the crashed handshake message was rejected as expected"); - } - // ClientHello with cookie - needInvalidRecords = false; + needInvalidRecords.set(false); System.out.println("invalidate ClientHello message"); if (ba[ba.length - 1] == (byte)0xFF) { ba[ba.length - 1] = (byte)0xFE; diff --git a/test/jdk/javax/net/ssl/SSLEngine/Basics.java b/test/jdk/javax/net/ssl/SSLEngine/Basics.java index 6e38c884e06..177422cb489 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/Basics.java +++ b/test/jdk/javax/net/ssl/SSLEngine/Basics.java @@ -26,8 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon * * This is intended to test many of the basic API calls to the SSLEngine * interface. This doesn't really exercise much of the SSL code. diff --git a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java index ec3a96c2b35..69d1e07621f 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java +++ b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java @@ -25,7 +25,7 @@ * @test * @bug 4948079 * @summary SSLEngineResult needs updating [none yet] - * @ignore the dependent implementation details are changed + * * @run main/othervm -Djsse.enableCBCProtection=false CheckStatus * * @author Brad Wetmore diff --git a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java index d6e32eff5de..a18444ccc7a 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java +++ b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java @@ -26,7 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore the dependent implementation details are changed * @author Brad Wetmore * * @run main/othervm ConnectionTest diff --git a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java index 8d60396fb91..1ddd9edfa59 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java +++ b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java @@ -26,7 +26,7 @@ * @bug 8133632 * @summary javax.net.ssl.SSLEngine does not properly handle received * SSL fatal alerts - * @ignore the dependent implementation details are changed + * * @run main/othervm EngineCloseOnAlert */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java index 475879a3262..5dc19f1475e 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java +++ b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java @@ -30,7 +30,6 @@ * @test * @bug 8180643 * @summary Illegal handshake message - * @ignore the dependent implementation details are changed * @run main/othervm IllegalHandshakeMessage */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java index aeb4c50aac9..cab26528790 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java +++ b/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java @@ -28,7 +28,7 @@ * @test * @bug 8042449 * @summary Issue for negative byte major record version - * @ignore the dependent implementation details are changed + * * @run main/othervm IllegalRecordVersion */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java index 9c633b58f70..3285479a86c 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java +++ b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java @@ -24,8 +24,7 @@ /* * @test * @bug 4495742 - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon + * * @run main/timeout=180 TestAllSuites * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java new file mode 100644 index 00000000000..fc5001e89b8 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8281236 + * @summary Check TLS connection behaviors for named groups configuration + * @library /javax/net/ssl/templates + * @run main/othervm NamedGroups + */ + +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; +import java.security.Security; + +public class NamedGroups extends SSLSocketTemplate { + private final String[] serverNamedGroups; + private final String[] clientNamedGroups; + private final boolean exceptionExpected; + + public NamedGroups(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) { + this.serverNamedGroups = serverNamedGroups; + this.clientNamedGroups = clientNamedGroups; + this.exceptionExpected = exceptionExpected; + } + + @Override + protected void configureServerSocket(SSLServerSocket sslServerSocket) { + SSLParameters sslParameters = sslServerSocket.getSSLParameters(); + sslParameters.setNamedGroups(serverNamedGroups); + sslServerSocket.setSSLParameters(sslParameters); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setNamedGroups(clientNamedGroups); + socket.setSSLParameters(sslParameters); + } + + @Override + protected void runServerApplication(SSLSocket socket) { + try { + super.runServerApplication(socket); + } catch (Exception ex) { + // Just ignore, let the client handle the failure information. + } + } + + @Override + protected void runClientApplication(SSLSocket sslSocket) throws Exception { + try { + super.runClientApplication(sslSocket); + } catch (Exception ex) { + if (!exceptionExpected) { + throw ex; + } else { // Otherwise, swallow the exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + runTest(new String[] { + "x25519", + "secp256r1" + }, + new String[] { + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + new String[] { + "secp256r1" + }, + false); + runTest(null, + new String[] { + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + null, + false); + runTest(new String[0], + new String[] { + "secp256r1" + }, + true); + runTest(new String[] { + "secp256r1" + }, + new String[0], + true); + runTest(new String[] { + "secp256NA" + }, + new String[] { + "secp256r1" + }, + true); + } + + private static void runTest(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) throws Exception { + new NamedGroups(serverNamedGroups, + clientNamedGroups, exceptionExpected).run(); + } +} diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java new file mode 100644 index 00000000000..9146e7b5f7b --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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 8281236 + * @summary check SSLParameters.setNamedGroups() implementation + */ + +import javax.net.ssl.SSLParameters; +import java.util.Arrays; + +public class NamedGroupsSpec { + public static void main(String[] args) throws Exception { + runTest(null, // null array should be allowed. + false); + runTest(new String[] { // empty array should be allowed + // blank line + }, + false); + runTest(new String[] { // multiple elements should be fine + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { // no duplicate element should be allowed + "x25519", + "x25519" + }, + true); + runTest(new String[] { // no null element should be allowed + null + }, + true); + runTest(new String[] { // no blank element should be allowed + "" + }, + true); + runTest(new String[] { // no blank element should be allowed + "x25519", + "" + }, + true); + runTest(new String[] { // no null element should be allowed. + "x25519", + null + }, + true); + } + + private static void runTest(String[] namedGroups, + boolean exceptionExpected) throws Exception { + SSLParameters sslParams = new SSLParameters(); + try { + sslParams.setNamedGroups(namedGroups); + } catch (Exception ex) { + if (!exceptionExpected || + !(ex instanceof IllegalArgumentException)) { + throw ex; + } else { // Otherwise, swallow the exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + + // Check if the getNamedGroups() method returns the same elements. + String[] configuredNamedGroups = sslParams.getNamedGroups(); + if (!Arrays.equals(namedGroups, configuredNamedGroups)) { + throw new RuntimeException( + "SSLParameters.getNamedGroups() method does not return " + + "the same elements as set with setNamedGroups()"); + } + } +} diff --git a/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java b/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java index ab17680cefc..bdf3368f5b0 100644 --- a/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java +++ b/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java @@ -99,7 +99,7 @@ public static void main(java.lang.String[] args) throws Exception { } catch (InterruptedException e) { if (!testPassed && testGeneratedInterrupt) { throw new RuntimeException("PageRanges option is not disabled " - + "for for Non serv-formatted flvrs"); + + "for Non serv-formatted flvrs"); } } if (!testGeneratedInterrupt) { diff --git a/test/jdk/javax/script/GetInterfaceTest.java b/test/jdk/javax/script/GetInterfaceTest.java index d379d2d10b7..2889f1448c8 100644 --- a/test/jdk/javax/script/GetInterfaceTest.java +++ b/test/jdk/javax/script/GetInterfaceTest.java @@ -35,7 +35,7 @@ public static void main(String[] args) throws Exception { ScriptEngine engine = manager.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No js engine engine found; test vacuously passes."); + System.out.println("Warning: No js engine found; test vacuously passes."); return; } diff --git a/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java b/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java index 23b995d6578..693ed910ba1 100644 --- a/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java +++ b/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { System.out.println("RFC2253 DN is " + xp.getName(X500Principal.RFC2253)); - System.out.println("CANONICAL DN is is " + + System.out.println("CANONICAL DN is " + xp.getName(X500Principal.CANONICAL)); String dn1 = xp.getName(X500Principal.CANONICAL); diff --git a/test/jdk/javax/sound/midi/Sequencer/SequencerState.java b/test/jdk/javax/sound/midi/Sequencer/SequencerState.java index 01b49e2e471..01b1c6a45d8 100644 --- a/test/jdk/javax/sound/midi/Sequencer/SequencerState.java +++ b/test/jdk/javax/sound/midi/Sequencer/SequencerState.java @@ -55,7 +55,7 @@ private static boolean hasSequencer() { public static void main(String[] args) throws Exception { - out("4913027: several Sequencer methods should should specify behaviour on closed Sequencer"); + out("4913027: several Sequencer methods should specify behaviour on closed Sequencer"); if (hasSequencer()) { boolean passed = testAll(); if (passed) { diff --git a/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java b/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java new file mode 100644 index 00000000000..03c940c2289 --- /dev/null +++ b/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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. + */ + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* + * @test + * @key sound + * @bug 8282578 + * @summary AIOOBE in javax.sound.sampled.Clip + * @run main EmptySysExMessageTest + */ + +public class EmptySysExMessageTest { + public static void main(String[] args) { + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String name = "zerosysex.mid"; + try { + readAudioFile(dir + sep + name); + } catch (Throwable t) { + throw new RuntimeException("Invalid file " + name + + " caused unexpected exception during read: " + + t + System.lineSeparator()); + } + } + + static void readAudioFile(String name) throws IOException { + File soundFile = new File(name); + Path path = Paths.get(soundFile.getAbsolutePath()); + byte[] samples = Files.readAllBytes(path); + + try { + AudioInputStream audioInputStream = + AudioSystem.getAudioInputStream(new ByteArrayInputStream(samples)); + try (Clip clip = AudioSystem.getClip()) { + clip.open(audioInputStream); + clip.start(); + Thread.sleep(1000); + clip.stop(); + } + } catch (UnsupportedAudioFileException + | LineUnavailableException + | IOException + | InterruptedException + | IllegalArgumentException + | IllegalStateException + | SecurityException expected) { + // Do nothing, these types of exception are expected on invalid file + } + } +} diff --git a/test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid b/test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid new file mode 100644 index 00000000000..cf92458b952 Binary files /dev/null and b/test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid differ diff --git a/test/jdk/javax/sql/testng/test/rowset/cachedrowset/CommonCachedRowSetTests.java b/test/jdk/javax/sql/testng/test/rowset/cachedrowset/CommonCachedRowSetTests.java index 7b04443e23f..642c03c9a45 100644 --- a/test/jdk/javax/sql/testng/test/rowset/cachedrowset/CommonCachedRowSetTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/cachedrowset/CommonCachedRowSetTests.java @@ -1401,7 +1401,7 @@ public void commonCachedRowSetTest0056(CachedRowSet rs) throws Exception { rs.updateString(2, coffee); rs.updateInt(5, sales); // MetaData should match - try ( // Get the original original RowSet and validate that the changes + try ( // Get the original RowSet and validate that the changes // are only made to the current, not the original ResultSet rs1 = rs.getOriginal()) { // MetaData should match @@ -1444,7 +1444,7 @@ public void commonCachedRowSetTest0057(CachedRowSet rs) throws Exception { rs.updateString(2, coffee); rs.updateInt(5, sales); // MetaData should match - try ( // Get the original original row and validate that the changes + try ( // Get the original row and validate that the changes // are only made to the current, not the original ResultSet rs1 = rs.getOriginalRow()) { // MetaData should match diff --git a/test/jdk/javax/sql/testng/test/rowset/serial/SerialDataLinkTests.java b/test/jdk/javax/sql/testng/test/rowset/serial/SerialDataLinkTests.java index 8e86d4a8f3d..0c7f19e85b1 100644 --- a/test/jdk/javax/sql/testng/test/rowset/serial/SerialDataLinkTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/serial/SerialDataLinkTests.java @@ -99,7 +99,7 @@ public void test04() throws Exception { /** * Validate that a SerialDatalink that is serialized & deserialized is not equal - * to to a SerialDatalink created using a different URL + * to a SerialDatalink created using a different URL */ @Test public void test05() throws Exception { diff --git a/test/jdk/javax/swing/AbstractButton/5049549/bug5049549.java b/test/jdk/javax/swing/AbstractButton/5049549/bug5049549.java index eb7ba2ddfd7..fd03f6e918d 100644 --- a/test/jdk/javax/swing/AbstractButton/5049549/bug5049549.java +++ b/test/jdk/javax/swing/AbstractButton/5049549/bug5049549.java @@ -41,13 +41,13 @@ public class bug5049549 { - private static ImageIcon DE = new ImageIcon(bug5049549.class.getResource("DE1.GIF")); - private static ImageIcon DI = new ImageIcon(bug5049549.class.getResource("DI1.GIF")); - private static ImageIcon DS = new ImageIcon(bug5049549.class.getResource("DS1.GIF")); - private static ImageIcon RO = new ImageIcon(bug5049549.class.getResource("RO1.GIF")); - private static ImageIcon RS = new ImageIcon(bug5049549.class.getResource("RS1.GIF")); - private static ImageIcon SE = new ImageIcon(bug5049549.class.getResource("SE1.GIF")); - private static ImageIcon PR = new ImageIcon(bug5049549.class.getResource("PR1.GIF")); + private static ImageIcon DE = new ImageIcon(bug5049549.class.getResource("DE1.gif")); + private static ImageIcon DI = new ImageIcon(bug5049549.class.getResource("DI1.gif")); + private static ImageIcon DS = new ImageIcon(bug5049549.class.getResource("DS1.gif")); + private static ImageIcon RO = new ImageIcon(bug5049549.class.getResource("RO1.gif")); + private static ImageIcon RS = new ImageIcon(bug5049549.class.getResource("RS1.gif")); + private static ImageIcon SE = new ImageIcon(bug5049549.class.getResource("SE1.gif")); + private static ImageIcon PR = new ImageIcon(bug5049549.class.getResource("PR1.gif")); private static Blocker blocker = new Blocker(); diff --git a/test/jdk/javax/swing/JColorChooser/Test4193384.java b/test/jdk/javax/swing/JColorChooser/Test4193384.java index 826e9893696..b32006e905c 100644 --- a/test/jdk/javax/swing/JColorChooser/Test4193384.java +++ b/test/jdk/javax/swing/JColorChooser/Test4193384.java @@ -51,7 +51,7 @@ private static void test(Color[] colors) { float[] hsb = new float[3]; for (int i = 0; i < colors.length; i++) { Color color = colors[i]; - // Make sure sure that there wasn't a regression + // Make sure that there wasn't a regression // in java.awt.Color and the conversion methods Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb); if (!color.equals(Color.getHSBColor(hsb[0], hsb[1], hsb[2]))) { diff --git a/test/jdk/javax/swing/JComboBox/JComboBoxBorderTest.java b/test/jdk/javax/swing/JComboBox/JComboBoxBorderTest.java index 2c508dccb36..cc93367eba1 100644 --- a/test/jdk/javax/swing/JComboBox/JComboBoxBorderTest.java +++ b/test/jdk/javax/swing/JComboBox/JComboBoxBorderTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 8054572 + * @requires (os.family == "mac") * @library /java/awt/regtesthelpers * @build PassFailJFrame * @summary Tests if JComboBox displays correctly when editable/non-editable @@ -92,4 +93,4 @@ public static void main(String[] args) throws Exception { pfjFrame.awaitAndCheck(); } -} \ No newline at end of file +} diff --git a/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java b/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java new file mode 100644 index 00000000000..0e176a911a3 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/TestComboBoxComponentRendering.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 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 8218474 + * @key headful + * @requires (os.family == "linux") + * @summary Verifies if combobox components are rendered correctly. + * @run main TestComboBoxComponentRendering + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.image.BufferedImage; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.io.File; +import javax.imageio.ImageIO; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class TestComboBoxComponentRendering { + private static JFrame frame; + private static JComboBox cb; + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoDelay(100); + + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + if (!laf.getClassName().contains("MotifLookAndFeel") && + !laf.getClassName().contains("MetalLookAndFeel")) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + doTesting(laf); + } + } + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported LAF: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static void doTesting(UIManager.LookAndFeelInfo laf) + throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + createAndShowUI(); + }); + boolean passed = false; + robot.waitForIdle(); + robot.delay(1000); + + Point pt = cb.getLocationOnScreen(); + BufferedImage img = robot.createScreenCapture( + new Rectangle(pt.x, pt.y, cb.getWidth(), cb.getHeight())); + for (int x = 20; x < img.getWidth()-20; ++x) { + for (int y = 20; y < img.getHeight()-20; ++y) { + if (img.getRGB(x,y) == Color.RED.getRGB()) { + passed = true; + break; + } + } + if (passed) + break; + } + + if (passed) { + System.out.println("Passed"); + } else { + ImageIO.write(img, "png", + new File("ComboBox.png")); + throw new RuntimeException("ComboBox components not rendered" + + " correctly for: " + laf.getClassName()); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" }; + frame = new JFrame(); + cb = new JComboBox(petStrings); + cb.setRenderer(new ComboBoxCustomRenderer()); + frame.pack(); + frame.add(cb); + frame.setSize(200,250); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} + +class ComboBoxCustomRenderer extends JLabel + implements ListCellRenderer { + + public ComboBoxCustomRenderer() { + setOpaque(true); + setHorizontalAlignment(CENTER); + setVerticalAlignment(CENTER); + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + setText(value.toString()); + setForeground(Color.RED); + return this; + } +} diff --git a/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java b/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java index 5cd5edcbbcc..b06dcdce3e9 100644 --- a/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java +++ b/test/jdk/javax/swing/JComboBox/TestComboBoxHeight.java @@ -24,7 +24,7 @@ /* * @test * @key headful - * @bug 4517214 + * @bug 4517214 8218474 * @summary Tests that comboBox is not doubleheight if editable and has TitledBorder */ diff --git a/test/jdk/javax/swing/JFileChooser/4847375/bug4847375.java b/test/jdk/javax/swing/JFileChooser/4847375/bug4847375.java index ffcb2cd502e..ed719dc1438 100644 --- a/test/jdk/javax/swing/JFileChooser/4847375/bug4847375.java +++ b/test/jdk/javax/swing/JFileChooser/4847375/bug4847375.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,14 @@ /* * @test - * @bug 4847375 8171363 + * @bug 4847375 8171363 8227257 * @requires (os.family == "windows") * @summary JFileChooser Create New Folder button is disabled incorrectly * @author Pavel Porvatov * @modules java.desktop/sun.awt * java.desktop/sun.awt.shell:+open + * @run main/othervm bug4847375 + * @run main/othervm -ea -esa bug4847375 */ import sun.awt.OSInfo; diff --git a/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java b/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java new file mode 100644 index 00000000000..0a8787e6045 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.BorderLayout; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JFrame; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.Icon; +import javax.swing.WindowConstants; +import javax.swing.filechooser.FileSystemView; + +/* + * @test + * @bug 8296198 + * @key headful + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Test to check if the Link to a folder is traversable with custom + * FileSystemView is valid on ValueChanged property listener. + * @run main/manual CustomFSVLinkTest + */ +public class CustomFSVLinkTest { + static JFrame frame; + static JFileChooser jfc; + + static PassFailJFrame passFailJFrame; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + initialize(); + } catch (InterruptedException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + }); + passFailJFrame.awaitAndCheck(); + } + + static void initialize() throws InterruptedException, InvocationTargetException { + //Initialize the components + final String INSTRUCTIONS = """ + Instructions to Test: + 1. Create a link to a any valid folder. + 2. Navigate to the linked folder through the link created + (From FileChooser). + 3. If "link" can't be traversed or if its absolute path is null + click FAIL. If "link" can be traversed then click PASS. + """; + frame = new JFrame("JFileChooser Link test"); + jfc = new JFileChooser(new MyFileSystemView()); + passFailJFrame = new PassFailJFrame("Test Instructions", INSTRUCTIONS, 5L, 8, 40); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + jfc.setControlButtonsAreShown(false); + jfc.setDialogType(JFileChooser.CUSTOM_DIALOG); + + frame.add(jfc, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } + + private static class MyFileSystemView extends FileSystemView { + FileSystemView delegate; + + MyFileSystemView() { + delegate = FileSystemView.getFileSystemView(); + } + + @Override + public File createNewFolder(File containingDir) throws IOException { + return delegate.createNewFolder(containingDir); + } + + @Override + public boolean isRoot(File f) { + return delegate.isRoot(f); + } + + @Override + public Boolean isTraversable(File f) { + return delegate.isTraversable(f); + } + + @Override + public String getSystemDisplayName(File f) { + return delegate.getSystemDisplayName(f); + } + + @Override + public String getSystemTypeDescription(File f) { + return delegate.getSystemTypeDescription(f); + } + + @Override + public Icon getSystemIcon(File f) { + return delegate.getSystemIcon(f); + } + + @Override + public boolean isParent(File folder, File file) { + return delegate.isParent(folder, file); + } + + @Override + public File getChild(File parent, String fileName) { + return delegate.getChild(parent, fileName); + } + + @Override + public boolean isFileSystem(File f) { + return delegate.isFileSystem(f); + } + + @Override + public boolean isHiddenFile(File f) { + return delegate.isHiddenFile(f); + } + + @Override + public boolean isFileSystemRoot(File dir) { + return delegate.isFileSystemRoot(dir); + } + + @Override + public boolean isDrive(File dir) { + return delegate.isDrive(dir); + } + + @Override + public boolean isFloppyDrive(File dir) { + return delegate.isFloppyDrive(dir); + } + + @Override + public boolean isComputerNode(File dir) { + return delegate.isComputerNode(dir); + } + + @Override + public File[] getRoots() { + return delegate.getRoots(); + } + + @Override + public File getHomeDirectory() { + return delegate.getHomeDirectory(); + } + + @Override + public File getDefaultDirectory() { + return delegate.getDefaultDirectory(); + } + + @Override + public File createFileObject(File dir, String filename) { + return delegate.createFileObject(dir, filename); + } + + @Override + public File createFileObject(String path) { + return delegate.createFileObject(path); + } + + @Override + public File[] getFiles(File dir, boolean useFileHiding) { + return delegate.getFiles(dir, useFileHiding); + } + + @Override + public File getParentDirectory(File dir) { + return delegate.getParentDirectory(dir); + } + + @Override + public File[] getChooserComboBoxFiles() { + return delegate.getChooserComboBoxFiles(); + } + + @Override + public boolean isLink(File file) { + return delegate.isLink(file); + } + + @Override + public File getLinkLocation(File file) throws FileNotFoundException { + return delegate.getLinkLocation(file); + } + } +} diff --git a/test/jdk/javax/swing/JFileChooser/FileSystemView/InaccessibleLink.java b/test/jdk/javax/swing/JFileChooser/FileSystemView/InaccessibleLink.java new file mode 100644 index 00000000000..95bb2e1411a --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileSystemView/InaccessibleLink.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; + +import javax.swing.filechooser.FileSystemView; + +/* + * @test + * @bug 8227257 + * @requires (os.family == "windows") + * @summary existing but inaccessible target for a link should be ignored + * @run main/othervm InaccessibleLink + * @run main/othervm -ea -esa InaccessibleLink + */ +public final class InaccessibleLink { + + /** + * The link to the windows-update settings. + */ + private static final byte[] bytes = { + 76, 0, 0, 0, 1, 20, 2, 0, 0, 0, 0, 0, -64, 0, 0, 0, 0, 0, 0, 70, + -127, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 20, 0, 31, 104, -128, 83, + 28, -121, -96, 66, 105, 16, -94, -22, 8, 0, 43, 48, 48, -99, 62, 0, + 97, -128, 0, 0, 0, 0, 109, 0, 115, 0, 45, 0, 115, 0, 101, 0, 116, 0, + 116, 0, 105, 0, 110, 0, 103, 0, 115, 0, 58, 0, 119, 0, 105, 0, 110, + 0, 100, 0, 111, 0, 119, 0, 115, 0, 117, 0, 112, 0, 100, 0, 97, 0, + 116, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + public static void main(String[] args) throws IOException { + File file = new File("inaccessible.lnk"); + try { + FileOutputStream fos = new FileOutputStream(file); + fos.write(bytes); + fos.close(); + + FileSystemView fsv = FileSystemView.getFileSystemView(); + if (!fsv.isLink(file)) { + throw new RuntimeException("not a link"); + } + File linkLocation = fsv.getLinkLocation(file); + if (linkLocation != null) { + throw new RuntimeException( + "location is not null: " + linkLocation); + } + } finally { + Files.deleteIfExists(file.toPath()); + } + } +} diff --git a/test/jdk/javax/swing/JMenuItem/JMenuItemSetAcceleratorTest.java b/test/jdk/javax/swing/JMenuItem/JMenuItemSetAcceleratorTest.java new file mode 100644 index 00000000000..ff96c2b3aec --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/JMenuItemSetAcceleratorTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016, 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. + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; + +/* + * @test + * @key headful + * @bug 8296275 + * @summary To verify the setAccelerator method of JMenuItem. + * @requires (os.family=="mac") + * @run main JMenuItemSetAcceleratorTest + */ + +public class JMenuItemSetAcceleratorTest { + private static JFrame frame; + private static final CountDownLatch actionLatch = new CountDownLatch(1); + private volatile static Point frameAt; + private volatile static Dimension frameSize; + + private static void createAndShow() { + frame = new JFrame("JMenuItem.setAccelerator"); + frame.setLayout(new FlowLayout()); + + JMenuBar bar = new JMenuBar(); + JMenu menu = new JMenu("File"); + JMenuItem menuItem = new JMenuItem("Menu Item"); + + menuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.META_DOWN_MASK)); + menuItem.addActionListener(e -> { + System.out.println("menu item action."); + actionLatch.countDown(); + }); + + menu.add(menuItem); + bar.add(menu); + + frame.setJMenuBar(bar); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(JMenuItemSetAcceleratorTest::createAndShow); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.setAutoWaitForIdle(true); + + EventQueue.invokeAndWait(() -> { + frameAt = frame.getLocationOnScreen(); + frameSize = frame.getSize(); + }); + + robot.mouseMove(frameAt.x + frameSize.width / 2, + frameAt.y + frameSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_META); + robot.keyPress(KeyEvent.VK_M); + robot.keyRelease(KeyEvent.VK_M); + robot.keyRelease(KeyEvent.VK_META); + + if (!actionLatch.await(5, TimeUnit.SECONDS)) { + throw new RuntimeException( + "Hasn't received the JMenuItem action event by pressing " + + "accelerator keys, test fails."); + } + System.out.println("Test passed, received action event on menu item."); + } finally { + SwingUtilities.invokeAndWait(JMenuItemSetAcceleratorTest::disposeFrame); + } + } + + public static void disposeFrame() { + if (frame != null) { + frame.dispose(); + } + } +} diff --git a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java index e783b147ca6..57ee1a2bb3f 100644 --- a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java +++ b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java @@ -23,7 +23,7 @@ /* * @test * @key headful - * @bug 4314194 8075916 + * @bug 4314194 8075916 8298083 * @summary Verifies disabled color for JCheckbox and JRadiobutton is honored in all L&F * @run main bug4314194 */ @@ -40,13 +40,14 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.synth.SynthLookAndFeel; public class bug4314194 { - private static JFrame frame; - private static JRadioButton radioButton; - private static JCheckBox checkBox; - private static Point point; - private static Rectangle rect; + private static volatile JFrame frame; + private static volatile JRadioButton radioButton; + private static volatile JCheckBox checkBox; + private static volatile Point point; + private static volatile Rectangle rect; private static Robot robot; private static final Color radioButtonColor = Color.RED; private static final Color checkboxColor = Color.GREEN; @@ -87,9 +88,25 @@ private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { } } - private static void createUI() { - UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); - UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + private static void createUI(String laf) { + if (UIManager.getLookAndFeel() instanceof SynthLookAndFeel) { + // reset "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", null); + UIManager.getDefaults().put("RadioButton.disabledText", null); + // set "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", checkboxColor); + // for some reason the RadioButton[Disabled] does not work + // see https://bugs.openjdk.org/browse/JDK-8298149 + //UIManager.getDefaults().put("RadioButton[Disabled].textForeground", radioButtonColor); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", radioButtonColor); + } else { + // reset "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", null); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", null); + // set "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); + UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + } checkBox = new JCheckBox("\u2588".repeat(5)); radioButton = new JRadioButton("\u2588".repeat(5)); @@ -98,7 +115,7 @@ private static void createUI() { checkBox.setEnabled(false); radioButton.setEnabled(false); - frame = new JFrame("bug4314194"); + frame = new JFrame(laf); frame.getContentPane().add(radioButton, BorderLayout.SOUTH); frame.getContentPane().add(checkBox, BorderLayout.NORTH); frame.pack(); @@ -122,7 +139,7 @@ public static void main(String[] args) throws Exception { System.out.println("Testing L&F: " + laf.getClassName()); SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); try { - SwingUtilities.invokeAndWait(() -> createUI()); + SwingUtilities.invokeAndWait(() -> createUI(laf.getName())); robot.waitForIdle(); robot.delay(1000); @@ -141,4 +158,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java index 597f5962587..3afddc3e37a 100644 --- a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java +++ b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java @@ -21,11 +21,16 @@ * questions. */ +import java.io.File; + +import java.awt.image.BufferedImage; +import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; import javax.swing.JFrame; @@ -38,8 +43,10 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.imageio.ImageIO; import static javax.swing.UIManager.getInstalledLookAndFeels; + /** * @test * @bug 4788637 7124307 @@ -52,15 +59,15 @@ public final class bug4788637 { private static JFrame fr; private static Robot robot; - private int step; - private boolean spinnerValueChanged[] = {false, false, false}; + private int step = 0; + private volatile boolean spinnerValueChanged[] = {false, false, false}; - private static Point p; - private static Rectangle rect; + private static volatile Point p; + private static volatile Rectangle rect; public static void main(final String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); robot.setAutoWaitForIdle(true); for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); @@ -68,6 +75,7 @@ public static void main(final String[] args) throws Exception { try { SwingUtilities.invokeAndWait(app::createAndShowGUI); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(()-> { spinner.requestFocus(); p = spinner.getLocationOnScreen(); @@ -106,9 +114,11 @@ public void stateChanged(ChangeEvent e) { public void start() { try { Thread.sleep(1000); + System.out.println("p " + p + " rect " + rect); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); - robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (bug4788637.this) { if (!spinnerValueChanged[step]) { bug4788637.this.wait(3000); @@ -123,6 +133,7 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); @@ -132,8 +143,10 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); } catch(Throwable t) { throw new RuntimeException(t); } @@ -145,6 +158,15 @@ public void destroy() { if (!spinnerValueChanged[0] || spinnerValueChanged[1] || !spinnerValueChanged[2]) { + System.out.println("!spinnerValueChanged[0] " + !spinnerValueChanged[0] + + " spinnerValueChanged[1] " + spinnerValueChanged[1] + + " !spinnerValueChanged[2] " + !spinnerValueChanged[2]); + try { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screen = new Rectangle(0, 0, (int) screenSize.getWidth(), (int) screenSize.getHeight()); + BufferedImage fullScreen = robot.createScreenCapture(screen); + ImageIO.write(fullScreen, "png", new File("fullScreen.png")); + } catch (Exception e) {} throw new Error("JSpinner buttons don't conform to most platform conventions"); } } diff --git a/test/jdk/javax/swing/JTable/JTableEditorNPE.java b/test/jdk/javax/swing/JTable/JTableEditorNPE.java new file mode 100644 index 00000000000..dd2da6accf8 --- /dev/null +++ b/test/jdk/javax/swing/JTable/JTableEditorNPE.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 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 6257207 + * @key headful + * @summary Verifies if JTable.getDefaultEditor throws NullPointerException + * @run main JTableEditorNPE + */ +import java.awt.Component; +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.SwingUtilities; + +public class JTableEditorNPE { + private static JFrame frame; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + frame.setSize(100, 100); + + DefaultTableModel myModel = new DefaultTableModel(); + myModel.addColumn("Col1"); + myModel.addColumn("Col2"); + myModel.addColumn("Col3"); + myModel.addRow(new Object[]{"item1.1", "item1.2", "item1.3"}); + myModel.addRow(new Object[]{"item2.1", "item2.2", "item2.3"}); + MyTable tbl = new MyTable(myModel); + frame.getContentPane().add(tbl); + frame.validate(); + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class MyTable extends JTable implements TableModelListener { + public MyTable(TableModel model) { + super(model); + } + + public void tableChanged(TableModelEvent event) { + super.tableChanged(event); + + int column = event.getColumn(); + if (column == TableModelEvent.ALL_COLUMNS) { + resizeAll(); + } else { + resize(column); + } + } + + protected void resizeAll() { + for (int i = 0; i < getModel().getColumnCount(); i++) { + resize(i); + } + } + + protected void resize(int column) { + TableCellEditor editor = null; + TableCellRenderer renderer = null; + Component comp; + int width=0; + for (int row = 0; row < getModel().getRowCount(); row++) { + editor = this.getCellEditor(row, column); + if (editor != null) { + comp = editor.getTableCellEditorComponent( + this, // table + getModel().getValueAt(row,column), // value + false, // isSelected + row, // row + column // column + ); + if (comp != null) { + width = Math.max(width, comp.getPreferredSize().width); + } + } + + renderer = this.getCellRenderer(row, column); + if (renderer != null) { + comp = renderer.getTableCellRendererComponent( + this, // table + getModel().getValueAt(row, column), // value + false, // isSelected + false, // hasFocus + row, // row + column // column + ); + if (comp != null) { + width = Math.max(width, comp.getPreferredSize().width); + } + } + } + + getColumnModel().getColumn(column).setPreferredWidth(width); + + this.revalidate(); + this.repaint(); + } + } +} + diff --git a/test/jdk/javax/swing/ProgressMonitor/ProgressTest.java b/test/jdk/javax/swing/ProgressMonitor/ProgressTest.java index e79bf7973b1..776cb720ae1 100644 --- a/test/jdk/javax/swing/ProgressMonitor/ProgressTest.java +++ b/test/jdk/javax/swing/ProgressMonitor/ProgressTest.java @@ -22,32 +22,29 @@ */ /* @test - * @bug 8054572 + * @bug 6445283 * @library /java/awt/regtesthelpers * @build PassFailJFrame - * @summary Tests if JComboBox displays correctly when editable/non-editable + * @summary Tests if ProgressMonitorInputStream reports progress accurately * @run main/manual ProgressTest */ import java.io.InputStream; -import javax.swing.JFrame; import javax.swing.ProgressMonitorInputStream; -import javax.swing.SwingUtilities; public class ProgressTest { private static final String instructionsText = - "A ProgressMonitor will be shown." + - " If it shows blank progressbar after 2048MB bytes read,"+ + "A ProgressMonitor will be shown.\n" + + " If it shows blank progressbar after 2048MB bytes read,\n"+ " press Fail else press Pass"; - private static JFrame frame; - public static void main(String[] args) throws Exception { PassFailJFrame pfjFrame = new PassFailJFrame("JScrollPane " + "Test Instructions", instructionsText, 5); + PassFailJFrame.positionTestWindow(null, PassFailJFrame.Position.VERTICAL); final long SIZE = (long) (Integer.MAX_VALUE * 1.5); @@ -85,6 +82,7 @@ public void run() { } }; thread.start(); + pfjFrame.awaitAndCheck(); } } diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index 5e2868ed506..ea8254c401a 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -246,6 +246,8 @@ private static JComponent createUI() { childPanel.add(Box.createHorizontalStrut(4)); contentPanel.add(childPanel); + contentPanel.add(Box.createVerticalStrut(4)); + if (textFieldSize == null) { textFieldSize = textField.getPreferredSize(); borderColor = tfBorder.getLineColor().getRGB(); @@ -254,6 +256,7 @@ private static JComponent createUI() { textField.setBounds(i, 0, textFieldSize.width, textFieldSize.height); childPanel.setBounds(0, (textFieldSize.height + 4) * i, textFieldSize.width + i + 4, textFieldSize.height); + panelLocations.add(childPanel.getLocation()); } contentPanel.setSize(textFieldSize.width + 4, @@ -261,11 +264,6 @@ private static JComponent createUI() { panelColor = contentPanel.getBackground().getRGB(); - // Save coordinates of the panels - for (Component comp : contentPanel.getComponents()) { - panelLocations.add(comp.getLocation()); - } - return contentPanel; } diff --git a/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java b/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java index 6b2331f390d..a0a7269b205 100644 --- a/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java +++ b/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -21,10 +21,17 @@ * questions. */ -import javax.swing.*; -import java.awt.*; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTextField; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; import java.awt.event.InputEvent; -import java.awt.image.BufferedImage; /** * @test @@ -39,7 +46,6 @@ public class HidingSelectionTest { private static JTextField field1; private static JTextField field2; private static JFrame frame; - private static Rectangle bounds; private static JMenu menu; private static JTextField anotherWindow; private static Point menuLoc; @@ -67,17 +73,9 @@ public static void main(String[] args) throws Exception { Robot robot = new Robot(); robot.waitForIdle(); robot.delay(200); - SwingUtilities.invokeAndWait(() -> { - bounds = field2.getBounds(); - bounds.setLocation(field2.getLocationOnScreen()); - }); - BufferedImage nosel = robot.createScreenCapture(bounds); SwingUtilities.invokeAndWait(field2::requestFocus); SwingUtilities.invokeAndWait(field2::selectAll); - robot.waitForIdle(); - robot.delay(200); - BufferedImage sel = robot.createScreenCapture(bounds); SwingUtilities.invokeAndWait(() -> { menuLoc = menu.getLocationOnScreen(); @@ -89,7 +87,7 @@ public static void main(String[] args) throws Exception { robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.waitForIdle(); robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), sel)) { + if (!field2.getCaret().isSelectionVisible()) { throw new RuntimeException("Test fails: menu hides selection"); } @@ -98,7 +96,7 @@ public static void main(String[] args) throws Exception { SwingUtilities.invokeAndWait(field1::requestFocus); robot.waitForIdle(); robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), nosel)) { + if (field2.getCaret().isSelectionVisible()) { throw new RuntimeException( "Test fails: focus lost doesn't hide selection"); } @@ -119,35 +117,12 @@ public static void main(String[] args) throws Exception { SwingUtilities.invokeAndWait(anotherWindow::requestFocus); robot.waitForIdle(); robot.delay(200); - if (biEqual(robot.createScreenCapture(bounds), nosel)) { + if (!field2.getCaret().isSelectionVisible()) { throw new RuntimeException( "Test fails: switch window hides selection"); } - SwingUtilities.invokeAndWait(anotherWindow::selectAll); - robot.waitForIdle(); - robot.delay(200); - if (biEqual(robot.createScreenCapture(bounds), sel)) { - throw new RuntimeException( - "Test fails: selection ownership is lost selection is shown"); - } - SwingUtilities.invokeLater(frame2::dispose); SwingUtilities.invokeLater(frame::dispose); } - - static boolean biEqual(BufferedImage i1, BufferedImage i2) { - if (i1.getWidth() == i2.getWidth() && - i1.getHeight() == i2.getHeight()) { - for (int x = 0; x < i1.getWidth(); x++) { - for (int y = 0; y < i1.getHeight(); y++) { - if (i1.getRGB(x, y) != i2.getRGB(x, y)) { - return false; - } - } - } - return true; - } - return false; - } } diff --git a/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java b/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java index c3cdafe8794..893afab5f4d 100644 --- a/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java +++ b/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -21,10 +21,17 @@ * questions. */ -import javax.swing.*; -import java.awt.*; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTextField; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; import java.awt.event.InputEvent; -import java.awt.image.BufferedImage; /** * @test @@ -40,131 +47,113 @@ public class MultiSelectionTest { private static JTextField field1; private static JTextField field2; private static JFrame frame; - private static Rectangle bounds; private static JMenu menu; private static JTextField anotherWindow; private static Point menuLoc; private static JFrame frame2; public static void main(String[] args) throws Exception { - SwingUtilities.invokeAndWait(() -> { - frame = new JFrame(); - field1 = new JTextField("field1 "); - field2 = new JTextField("field2 "); - field1.setEditable(false); - field2.setEditable(false); - frame.getContentPane().setLayout(new FlowLayout()); - frame.getContentPane().add(field1); - frame.getContentPane().add(field2); - JMenuBar menuBar = new JMenuBar(); - menu = new JMenu("menu"); - menu.add(new JMenuItem("item")); - menuBar.add(menu); - frame.setJMenuBar(menuBar); - frame.pack(); - frame.setVisible(true); - }); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + field1 = new JTextField("field1 "); + field2 = new JTextField("field2 "); + field1.setEditable(false); + field2.setEditable(false); + frame.getContentPane().setLayout(new FlowLayout()); + frame.getContentPane().add(field1); + frame.getContentPane().add(field2); + JMenuBar menuBar = new JMenuBar(); + menu = new JMenu("menu"); + menu.add(new JMenuItem("item")); + menuBar.add(menu); + frame.setJMenuBar(menuBar); + frame.pack(); + frame.setVisible(true); + }); - Robot robot = new Robot(); - robot.waitForIdle(); - robot.delay(200); - SwingUtilities.invokeAndWait(() -> { - bounds = field2.getBounds(); - bounds.setLocation(field2.getLocationOnScreen()); - }); - BufferedImage nosel = robot.createScreenCapture(bounds); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(200); - SwingUtilities.invokeAndWait(field2::requestFocus); - SwingUtilities.invokeAndWait(field2::selectAll); - robot.waitForIdle(); - robot.delay(200); - BufferedImage sel = robot.createScreenCapture(bounds); + SwingUtilities.invokeAndWait(field2::requestFocus); + SwingUtilities.invokeAndWait(field2::selectAll); + robot.waitForIdle(); + robot.delay(200); - SwingUtilities.invokeAndWait(() -> { - menuLoc = menu.getLocationOnScreen(); - menuLoc.translate(10, 10); - }); - robot.mouseMove(menuLoc.x, menuLoc.y); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.delay(50); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - robot.waitForIdle(); - robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), sel)) { - throw new RuntimeException("Test fails: menu hides selection"); - } - - SwingUtilities.invokeAndWait( - MenuSelectionManager.defaultManager()::clearSelectedPath); - SwingUtilities.invokeAndWait(field1::requestFocus); - robot.waitForIdle(); - robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), sel)) { - throw new RuntimeException( - "Test fails: focus lost hides single selection"); - } - - SwingUtilities.invokeAndWait(field1::selectAll); - robot.waitForIdle(); - robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), nosel)) { - throw new RuntimeException( - "Test fails: focus lost doesn't hide selection upon multi selection"); - } + SwingUtilities.invokeAndWait(() -> { + menuLoc = menu.getLocationOnScreen(); + menuLoc.translate(10, 10); + }); + robot.mouseMove(menuLoc.x, menuLoc.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(200); + if (!field2.getCaret().isSelectionVisible()) { + throw new RuntimeException("Test fails: menu hides selection"); + } - SwingUtilities.invokeAndWait(field2::requestFocus); - robot.waitForIdle(); - robot.delay(200); - if (!biEqual(robot.createScreenCapture(bounds), sel)) { - throw new RuntimeException( - "Test fails: focus gain hides selection upon multi selection"); - } + SwingUtilities.invokeAndWait( + MenuSelectionManager.defaultManager()::clearSelectedPath); + SwingUtilities.invokeAndWait(field1::requestFocus); + robot.waitForIdle(); + robot.delay(200); + if (field2.getSelectedText() == null || field2.getSelectedText().length() == 0) { + throw new RuntimeException( + "Test fails: focus lost hides single selection"); + } - SwingUtilities.invokeAndWait(field2::requestFocus); - robot.waitForIdle(); - SwingUtilities.invokeAndWait(() ->{ - frame2 = new JFrame(); - Point loc = frame.getLocationOnScreen(); - loc.translate(0, frame.getHeight()); - frame2.setLocation(loc); - anotherWindow = new JTextField("textField3"); - frame2.add(anotherWindow); - frame2.pack(); - frame2.setVisible(true); - }); - robot.waitForIdle(); - SwingUtilities.invokeAndWait(anotherWindow::requestFocus); - robot.waitForIdle(); - robot.delay(200); - if (biEqual(robot.createScreenCapture(bounds), nosel)) { - throw new RuntimeException( - "Test fails: switch window hides selection"); - } + SwingUtilities.invokeAndWait(field1::selectAll); + robot.waitForIdle(); + robot.delay(200); + if (field2.getCaret().isSelectionVisible()) { + throw new RuntimeException( + "Test fails: focus lost doesn't hide selection upon multi selection"); + } - SwingUtilities.invokeAndWait(anotherWindow::selectAll); - robot.waitForIdle(); - robot.delay(200); - if (biEqual(robot.createScreenCapture(bounds), sel)) { - throw new RuntimeException( - "Test fails: selection ownership is lost selection is shown"); - } + SwingUtilities.invokeAndWait(field2::requestFocus); + robot.waitForIdle(); + robot.delay(200); + if (!field2.getCaret().isSelectionVisible()) { + throw new RuntimeException( + "Test fails: focus gain hides selection upon multi selection"); + } - SwingUtilities.invokeLater(frame2::dispose); - SwingUtilities.invokeLater(frame::dispose); - } + SwingUtilities.invokeAndWait(field2::requestFocus); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + frame2 = new JFrame(); + Point loc = frame.getLocationOnScreen(); + loc.translate(0, frame.getHeight()); + frame2.setLocation(loc); + anotherWindow = new JTextField("textField3"); + frame2.add(anotherWindow); + frame2.pack(); + frame2.setVisible(true); + }); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(anotherWindow::requestFocus); + robot.waitForIdle(); + robot.delay(200); + if (!field2.getCaret().isSelectionVisible()) { + throw new RuntimeException( + "Test fails: switch window hides selection"); + } - static boolean biEqual(BufferedImage i1, BufferedImage i2) { - if (i1.getWidth() == i2.getWidth() && - i1.getHeight() == i2.getHeight()) { - for (int x = 0; x < i1.getWidth(); x++) { - for (int y = 0; y < i1.getHeight(); y++) { - if (i1.getRGB(x, y) != i2.getRGB(x, y)) { - return false; - } - } + SwingUtilities.invokeAndWait(anotherWindow::selectAll); + robot.waitForIdle(); + robot.delay(200); + if (field2.getCaret().isSelectionVisible()) { + throw new RuntimeException( + "Test fails: selection ownership is lost selection is shown"); + } + } finally { + if (frame2 != null) { + SwingUtilities.invokeLater(frame2::dispose); } - return true; + SwingUtilities.invokeLater(frame::dispose); } - return false; } } diff --git a/test/jdk/javax/xml/jaxp/testng/parse/XMLEntityScannerLoad.java b/test/jdk/javax/xml/jaxp/testng/parse/XMLEntityScannerLoad.java index 308f17382fc..eac91f7fdc9 100644 --- a/test/jdk/javax/xml/jaxp/testng/parse/XMLEntityScannerLoad.java +++ b/test/jdk/javax/xml/jaxp/testng/parse/XMLEntityScannerLoad.java @@ -39,7 +39,7 @@ * https://bugs.openjdk.org/browse/JDK-8059327 * * Also: - * JDK-8061550: XMLEntityScanner can corrupt corrupt content during parsing + * JDK-8061550: XMLEntityScanner can corrupt content during parsing * https://bugs.openjdk.org/browse/JDK-8061550 * * @Summary: verify that the character cache in XMLEntityScanner is reset properly diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java new file mode 100644 index 00000000000..f2b2c470ae7 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 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 + * @summary Stress test ScopedValue with many bindings and rebinings + * @enablePreview + * @modules jdk.incubator.concurrent + * @library /test/lib + * @key randomness + * @run testng ManyBindings + */ + +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.ScopedValue.Carrier; +import java.util.Arrays; +import java.util.Objects; +import java.util.Random; + +import jdk.test.lib.RandomFactory; +import jdk.test.lib.thread.VThreadRunner; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class ManyBindings { + private static final Random RND = RandomFactory.getRandom(); + + // number of scoped values to create + private static final int SCOPED_VALUE_COUNT = 16; + + // recursive depth to test + private static final int MAX_DEPTH = 24; + + /** + * Stress test bindings on platform thread. + */ + public void testPlatformThread() { + test(); + } + + /** + * Stress test bindings on virtual thread. + */ + public void testVirtualThread() throws Exception { + VThreadRunner.run(() -> test()); + } + + /** + * Scoped value and its expected value (or null if not bound). + */ + record KeyAndValue(ScopedValue key, T value) { + KeyAndValue() { + this(ScopedValue.newInstance(), null); + } + } + + /** + * Stress test bindings on current thread. + */ + private void test() { + KeyAndValue[] array = new KeyAndValue[SCOPED_VALUE_COUNT]; + for (int i = 0; i < array.length; i++) { + array[i] = new KeyAndValue<>(); + } + test(array, 1); + } + + /** + * Test that the scoped values in the array have the expected value, then + * recursively call this method with some of the scoped values bound to a + * new value. + * + * @param array the scoped values and their expected value + * @param depth current recurive depth + */ + private void test(KeyAndValue[] array, int depth) { + if (depth > MAX_DEPTH) + return; + + // check that the scoped values have the expected values + check(array); + + // try to pollute the cache + lotsOfReads(array); + + // create a Carrier to bind/rebind some of the scoped values + int len = array.length; + Carrier carrier = null; + + KeyAndValue[] newArray = Arrays.copyOf(array, len); + int n = Math.max(1, RND.nextInt(len / 2)); + while (n > 0) { + int index = RND.nextInt(len); + ScopedValue key = array[index].key; + int newValue = RND.nextInt(); + if (carrier == null) { + carrier = ScopedValue.where(key, newValue); + } else { + carrier = carrier.where(key, newValue); + } + newArray[index] = new KeyAndValue<>(key, newValue); + n--; + } + + // invoke recursively + carrier.run(() -> { + test(newArray, depth+1); + }); + + // check that the scoped values have the origina values + check(array); + } + + /** + * Check that the given scoped values have the expected value. + */ + private void check(KeyAndValue[] array) { + for (int i = 0; i < array.length; i++) { + ScopedValue key = array[i].key; + Integer value = array[i].value; + if (value == null) { + assertFalse(key.isBound()); + } else { + assertEquals(key.get(), value); + } + } + } + + /** + * Do lots of reads of the scoped values, to pollute the SV cache. + */ + private void lotsOfReads(KeyAndValue[] array) { + for (int k = 0; k < 1000; k++) { + int index = RND.nextInt(array.length); + Integer value = array[index].value; + if (value != null) { + ScopedValue key = array[index].key; + assertEquals(key.get(), value); + } + } + } +} diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java new file mode 100644 index 00000000000..690f974a539 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2021, 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 + * @summary Test ScopedValue API + * @enablePreview + * @modules jdk.incubator.concurrent + * @run testng ScopeValueAPI + */ + +import jdk.incubator.concurrent.ScopedValue; +import java.util.NoSuchElementException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class ScopeValueAPI { + + @DataProvider + public Object[][] factories() { + return new Object[][] { + { Thread.ofPlatform().factory() }, + { Thread.ofVirtual().factory() }, + }; + } + + /** + * Test that the run method is invoked. + */ + @Test(dataProvider = "factories") + public void testRun(ThreadFactory factory) throws Exception { + test(factory, () -> { + class Box { static boolean executed; } + ScopedValue name = ScopedValue.newInstance(); + ScopedValue.where(name, "duke", () -> { Box.executed = true; }); + assertTrue(Box.executed); + }); + } + + /** + * Test the run method throwing an exception. + */ + @Test(dataProvider = "factories") + public void testRunThrows(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + Runnable op = () -> { throw new FooException(); }; + assertThrows(FooException.class, () -> ScopedValue.where(name, "duke", op)); + assertFalse(name.isBound()); + }); + } + + /** + * Test that the call method is invoked. + */ + @Test(dataProvider = "factories") + public void testCall(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + String result = ScopedValue.where(name, "duke", name::get); + assertEquals(result, "duke"); + }); + } + + /** + * Test the call method throwing an exception. + */ + @Test(dataProvider = "factories") + public void testCallThrows(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + Callable op = () -> { throw new FooException(); }; + assertThrows(FooException.class, () -> ScopedValue.where(name, "duke", op)); + assertFalse(name.isBound()); + }); + } + + /** + * Test get method. + */ + @Test(dataProvider = "factories") + public void testGet(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + + // run + ScopedValue.where(name1, "duke", () -> { + assertEquals(name1.get(), "duke"); + assertThrows(NoSuchElementException.class, name2::get); + + }); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + + // call + ScopedValue.where(name1, "duke", () -> { + assertEquals(name1.get(), "duke"); + assertThrows(NoSuchElementException.class, name2::get); + return null; + }); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + }); + } + + /** + * Test isBound method. + */ + @Test(dataProvider = "factories") + public void testIsBound(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + + // run + ScopedValue.where(name1, "duke", () -> { + assertTrue(name1.isBound()); + assertFalse(name2.isBound()); + }); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + + // call + ScopedValue.where(name1, "duke", () -> { + assertTrue(name1.isBound()); + assertFalse(name2.isBound()); + return null; + }); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + }); + } + + /** + * Test orElse method. + */ + @Test(dataProvider = "factories") + public void testOrElse(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + assertTrue(name.orElse(null) == null); + assertEquals(name.orElse("default"), "default"); + + // run + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElse(null), "duke"); + assertEquals(name.orElse("default"), "duke"); + }); + + // call + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElse(null), "duke"); + assertEquals(name.orElse("default"), "duke"); + return null; + }); + }); + } + + /** + * Test orElseThrow method. + */ + @Test(dataProvider = "factories") + public void testOrElseThrow(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + assertThrows(FooException.class, () -> name.orElseThrow(FooException::new)); + + // run + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElseThrow(FooException::new), "duke"); + }); + + // call + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElseThrow(FooException::new), "duke"); + return null; + }); + }); + } + + /** + * Test two bindings. + */ + @Test(dataProvider = "factories") + public void testTwoBindings(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue age = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke").where(age, 100).run(() -> { + assertTrue(name.isBound()); + assertTrue(age.isBound()); + assertEquals(name.get(), "duke"); + assertEquals((int) age.get(), 100); + }); + assertFalse(name.isBound()); + assertFalse(age.isBound()); + + // call + ScopedValue.where(name, "duke").where(age, 100).call(() -> { + assertTrue(name.isBound()); + assertTrue(age.isBound()); + assertEquals(name.get(), "duke"); + assertEquals((int) age.get(), 100); + return null; + }); + assertFalse(name.isBound()); + assertFalse(age.isBound()); + + }); + } + + /** + * Test rebinding. + */ + @Test(dataProvider = "factories") + public void testRebinding(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + return null; + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test rebinding from null vaue to another value. + */ + @Test(dataProvider = "factories") + public void testRebindingFromNull(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), null); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + }); + + assertTrue(name.isBound()); + assertTrue(name.get() == null); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), null); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + return null; + }); + + assertTrue(name.isBound()); + assertTrue(name.get() == null); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test rebinding to null value. + */ + @Test(dataProvider = "factories") + public void testRebindingToNull(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertTrue(name.get() == null); + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertTrue(name.get() == null); + return null; + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test Carrier.get. + */ + @Test(dataProvider = "factories") + public void testCarrierGet(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue age = ScopedValue.newInstance(); + + // one scoped value + var carrier1 = ScopedValue.where(name, "duke"); + assertEquals(carrier1.get(name), "duke"); + assertThrows(NoSuchElementException.class, () -> carrier1.get(age)); + + // two scoped values + var carrier2 = carrier1.where(age, 20); + assertEquals(carrier2.get(name), "duke"); + assertEquals((int) carrier2.get(age), 20); + }); + } + + /** + * Test NullPointerException. + */ + public void testNullPointerException() { + ScopedValue name = ScopedValue.newInstance(); + + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value")); + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value", () -> { })); + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value", () -> null)); + + assertThrows(NullPointerException.class, () -> name.orElseThrow(null)); + + var carrier = ScopedValue.where(name, "duke"); + assertThrows(NullPointerException.class, () -> carrier.where(null, "value")); + assertThrows(NullPointerException.class, () -> carrier.get(null)); + assertThrows(NullPointerException.class, () -> carrier.run(null)); + assertThrows(NullPointerException.class, () -> carrier.call(null)); + } + + @FunctionalInterface + private interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * Run the given task in a thread created with the given thread factory. + * @throws Exception if the task throws an exception + */ + private static void test(ThreadFactory factory, ThrowingRunnable task) throws Exception { + try (var executor = Executors.newThreadPerTaskExecutor(factory)) { + var future = executor.submit(() -> { + task.run(); + return null; + }); + try { + future.get(); + } catch (ExecutionException ee) { + Throwable cause = ee.getCause(); + if (cause instanceof Exception e) + throw e; + if (cause instanceof Error e) + throw e; + throw new RuntimeException(cause); + } + } + } +} diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java new file mode 100644 index 00000000000..c5e6cd54589 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021, 2022 Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary StressStackOverflow the recovery path for ScopedValue + * @modules jdk.incubator.concurrent + * @compile --enable-preview -source ${jdk.version} StressStackOverflow.java + * @run main/othervm/timeout=300 -XX:-TieredCompilation --enable-preview StressStackOverflow + * @run main/othervm/timeout=300 -XX:TieredStopAtLevel=1 --enable-preview StressStackOverflow + * @run main/othervm/timeout=300 --enable-preview StressStackOverflow + */ + +import java.util.concurrent.Callable; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadLocalRandom; +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructureViolationException; +import jdk.incubator.concurrent.StructuredTaskScope; + +public class StressStackOverflow { + public static final ScopedValue el = ScopedValue.newInstance(); + + public static final ScopedValue inheritedValue = ScopedValue.newInstance(); + + final ThreadLocalRandom tlr = ThreadLocalRandom.current(); + static final TestFailureException testFailureException = new TestFailureException("Unexpected value for ScopedValue"); + int ITERS = 1_000_000; + + static class TestFailureException extends RuntimeException { + TestFailureException(String s) { super(s); } + } + + // Test the ScopedValue recovery mechanism for stack overflows. We implement both Callable + // and Runnable interfaces. Which one gets tested depends on the constructor argument. + class DeepRecursion implements Callable, Runnable { + + static enum Behaviour {CALL, RUN} + final Behaviour behaviour; + + public DeepRecursion(Behaviour behaviour) { + this.behaviour = behaviour; + } + + public void run() { + final var last = el.get(); + ITERS--; + var nextRandomFloat = tlr.nextFloat(); + try { + switch (behaviour) { + case CALL -> + ScopedValue.where(el, el.get() + 1).call(() -> fibonacci_pad(20, this)); + case RUN -> + ScopedValue.where(el, el.get() + 1).run(() -> fibonacci_pad(20, this)); + } + if (!last.equals(el.get())) { + throw testFailureException; + } + } catch (StackOverflowError e) { + if (nextRandomFloat <= 0.1) { + ScopedValue.where(el, el.get() + 1).run(this); + } + } catch (TestFailureException e) { + throw e; + } catch (Throwable throwable) { + // StackOverflowErrors cause many different failures. These include + // StructureViolationExceptions and InvocationTargetExceptions. This test + // checks that, no matter what the failure mode, scoped values are handled + // correctly. + } finally { + if (!last.equals(el.get())) { + throw testFailureException; + } + } + + Thread.yield(); + } + + public Object call() { + run(); + return null; + } + } + + static final Runnable nop = new Runnable() { + public void run() { } + }; + + // Consume some stack. + // + + // The double recursion used here prevents an optimizing JIT from + // inlining all the recursive calls, which would make it + // ineffective. + private long fibonacci_pad1(int n, Runnable op) { + if (n <= 1) { + op.run(); + return n; + } + return fibonacci_pad1(n - 1, op) + fibonacci_pad1(n - 2, nop); + } + + private static final Integer I_42 = 42; + + long fibonacci_pad(int n, Runnable op) { + final var last = el.get(); + try { + return fibonacci_pad1(tlr.nextInt(n), op); + } catch (StackOverflowError err) { + if (!inheritedValue.get().equals(I_42)) { + throw testFailureException; + } + if (!last.equals(el.get())) { + throw testFailureException; + } + throw err; + } + } + + // Run op in a new thread. Platform or virtual threads are chosen at random. + void runInNewThread(Runnable op) { + var threadFactory + = (tlr.nextBoolean() ? Thread.ofPlatform() : Thread.ofVirtual()).factory(); + try (var scope = new StructuredTaskScope("", threadFactory)) { + var future = scope.fork(() -> { + op.run(); + return null; + }); + future.get(); + scope.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void run() { + try { + ScopedValue.where(inheritedValue, 42).where(el, 0).run(() -> { + try (var scope = new StructuredTaskScope()) { + try { + if (tlr.nextBoolean()) { + // Repeatedly test Scoped Values set by ScopedValue::call() and ScopedValue::run() + final var deepRecursion + = new DeepRecursion(tlr.nextBoolean() ? DeepRecursion.Behaviour.CALL : DeepRecursion.Behaviour.RUN); + deepRecursion.run(); + } else { + // Recursively run ourself until we get a stack overflow + // Catch the overflow and make sure the recovery path works + // for values inherited from a StructuredTaskScope. + Runnable op = new Runnable() { + public void run() { + try { + fibonacci_pad(20, this); + } catch (StackOverflowError e) { + } catch (TestFailureException e) { + throw e; + } catch (Throwable throwable) { + // StackOverflowErrors cause many different failures. These include + // StructureViolationExceptions and InvocationTargetExceptions. This test + // checks that, no matter what the failure mode, scoped values are handled + // correctly. + } finally { + if (!inheritedValue.get().equals(I_42)) { + throw testFailureException; + } + } + } + }; + runInNewThread(op); + } + scope.join(); + } catch (StructureViolationException structureViolationException) { + // Can happen if a stack overflow prevented a StackableScope from + // being removed. We can continue. + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } catch (StructureViolationException structureViolationException) { + // Can happen if a stack overflow prevented a StackableScope from + // being removed. We can continue. + } + } + + public static void main(String[] args) { + var torture = new StressStackOverflow(); + while (torture.ITERS > 0) { + torture.run(); + } + System.out.println("OK"); + } +} diff --git a/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java b/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java new file mode 100644 index 00000000000..a6917ccf6ab --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 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 + * @summary Basic tests for StructuredTaskScope with scoped values + * @enablePreview + * @modules jdk.incubator.concurrent + * @run testng WithScopedValue + */ + +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructuredTaskScope; +import jdk.incubator.concurrent.StructureViolationException; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class WithScopedValue { + + @DataProvider + public Object[][] factories() { + return new Object[][] { + { Thread.ofPlatform().factory() }, + { Thread.ofVirtual().factory() }, + }; + } + + /** + * Test that fork inherits a scoped value into a child thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope = new StructuredTaskScope(null, factory)) { + Future future = scope.fork(() -> { + return name.get(); // child should read "x" + }); + scope.join(); + return future.resultNow(); + } + }); + assertEquals(value, "x"); + } + + /** + * Test that fork inherits a scoped value into a grandchild thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope1 = new StructuredTaskScope(null, factory)) { + Future future1 = scope1.fork(() -> { + try (var scope2 = new StructuredTaskScope(null, factory)) { + Future future2 = scope2.fork(() -> { + return name.get(); // grandchild should read "x" + }); + scope2.join(); + return future2.resultNow(); + } + }); + scope1.join(); + return future1.resultNow(); + } + }); + assertEquals(value, "x"); + } + + /** + * Test that fork inherits a rebound scoped value into a grandchild thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue3(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope1 = new StructuredTaskScope(null, factory)) { + Future future1 = scope1.fork(() -> { + assertEquals(name.get(), "x"); // child should read "x" + + // rebind name to "y" + String grandchildValue = ScopedValue.where(name, "y", () -> { + try (var scope2 = new StructuredTaskScope(null, factory)) { + Future future2 = scope2.fork(() -> { + return name.get(); // grandchild should read "y" + }); + scope2.join(); + return future2.resultNow(); + } + }); + + assertEquals(name.get(), "x"); // child should read "x" + return grandchildValue; + }); + scope1.join(); + return future1.resultNow(); + } + }); + assertEquals(value, "y"); + } + + /** + * Test exiting a dynamic scope with an open task scope. + */ + public void testStructureViolation1() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + class Box { + StructuredTaskScope scope; + } + var box = new Box(); + try { + try { + ScopedValue.where(name, "x", () -> { + box.scope = new StructuredTaskScope(); + }); + fail(); + } catch (StructureViolationException expected) { } + + // underlying flock should be closed, fork should return a cancelled task + StructuredTaskScope scope = box.scope; + AtomicBoolean ran = new AtomicBoolean(); + Future future = scope.fork(() -> { + ran.set(true); + return null; + }); + assertTrue(future.isCancelled()); + scope.join(); + assertFalse(ran.get()); + + } finally { + StructuredTaskScope scope = box.scope; + if (scope != null) { + scope.close(); + } + } + } + + /** + * Test closing a StructuredTaskScope while executing in a dynamic scope. + */ + public void testStructureViolation2() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name, "x", () -> { + assertThrows(StructureViolationException.class, scope::close); + }); + } + } + + /** + * Test fork when a scoped value is bound after a StructuredTaskScope is created. + */ + public void testStructureViolation3() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name, "x", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + } + + /** + * Test fork when a scoped value is re-bound after a StructuredTaskScope is created. + */ + public void testStructureViolation4() throws Exception { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + + // rebind + ScopedValue.where(name1, "x", () -> { + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name1, "y", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + }); + + // new binding + ScopedValue.where(name1, "x", () -> { + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name2, "y", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + }); + } +} diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java index a664f65092b..8139931f41d 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java @@ -22,7 +22,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collection; @@ -36,25 +36,23 @@ public class AbstractVectorLoadStoreTest extends AbstractVectorTest { ByteOrder.BIG_ENDIAN, ByteOrder.LITTLE_ENDIAN); static final List> BYTE_BUFFER_GENERATORS = List.of( - withToString("HB:RW:NE", (int s) -> { - return ByteBuffer.allocate(s) - .order(ByteOrder.nativeOrder()); - }), - withToString("DB:RW:NE", (int s) -> { - return ByteBuffer.allocateDirect(s) - .order(ByteOrder.nativeOrder()); - }), - withToString("MS:RW:NE", (int s) -> { - return MemorySegment.allocateNative(s, MemorySession.openImplicit()) + withToString("HB:RW:NE", (int s) -> + ByteBuffer.allocate(s) + .order(ByteOrder.nativeOrder())), + withToString("DB:RW:NE", (int s) -> + ByteBuffer.allocateDirect(s) + .order(ByteOrder.nativeOrder())), + withToString("MS:RW:NE", (int s) -> + MemorySegment.allocateNative(s, SegmentScope.auto()) .asByteBuffer() - .order(ByteOrder.nativeOrder()); - }) + .order(ByteOrder.nativeOrder()) + ) ); static final List> MEMORY_SEGMENT_GENERATORS = List.of( - withToString("HMS", (int s) -> { - return MemorySegment.allocateNative(s, MemorySession.openImplicit()); - }), + withToString("HMS", (int s) -> + MemorySegment.allocateNative(s, SegmentScope.auto()) + ), withToString("DMS", (int s) -> { byte[] b = new byte[s]; return MemorySegment.ofArray(b); @@ -62,4 +60,3 @@ public class AbstractVectorLoadStoreTest extends AbstractVectorTest { ); } - diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java index 930c8ce791e..c588b03fb68 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java index 0c52ddde4f3..0a60dc2742c 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java index c9990cdf2ce..807a1647532 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java index 10312b7cb5f..1274106caff 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java index a9042cb65f9..1d956bc339c 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java index 68dd22c966e..4ff63cf1fda 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java index b6a3fe5fe61..ef3ab3d5b26 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java index 99b44ada0aa..4a3a0bc4f8a 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java index b69de8938a5..7d242995c1f 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java index eb8d201bee5..137f7ba5791 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java index 2efaf867c66..719b803b69b 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java index 18baffa0e90..26f2f02883f 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java index d1ba7a644de..53e75fa62c7 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java index 83ecf751cb5..6ea43adfec4 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java index 64148eaabdb..f67bf1e3267 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java index 7ddc9f6ee55..d6bf4dedc3e 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java index 97b2e1ecc14..c2d0077a8cd 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java index d6e3f18a2c5..e9b70d9c93b 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java index b9157d93295..28633c1b345 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java index 2891c0c142e..f128184026b 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java index cebd1c4cb32..81b5ebd8fff 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java index 2be1356e3bd..ca6d4d74243 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java index 43cb1898573..5ad19715622 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java index 48a3e94bbbb..1041d47d96c 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java index e21cedfae09..e20d33d2026 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java index 13b59c5ffbc..2a153318cae 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java index ad2204cc822..407f5affdf4 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java index fb04ca5779d..d32d6735030 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java index 157a0638bdb..6ab8817b22d 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java index 1129f5cd83a..7fb1c43ba3b 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index 8c495bc4f96..8a009bb9fb9 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -223,6 +223,7 @@ function gen_op_tmpl { replace_variables $unit_filename $unit_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" "$kernel_smoke" local gen_perf_tests=$generate_perf_tests + gen_perf_tests=true if [[ $template == *"-Broadcast-"* ]] || [[ $template == "Miscellaneous" ]] || [[ $template == *"Compare-Masked"* ]] || [[ $template == *"Compare-Broadcast"* ]]; then gen_perf_tests=false diff --git a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template index 7e27bfe96bf..ada362cee8f 100644 --- a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template +++ b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template @@ -37,7 +37,7 @@ #warn This file is preprocessed before being compiled import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.$Type$Vector; import jdk.incubator.vector.VectorMask; @@ -499,8 +499,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction<$type$[]> fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -528,8 +528,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction<$type$[]> fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -592,8 +592,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction<$type$[]> fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask<$Boxtype$> vmask = VectorMask.fromValues(SPECIES, mask); @@ -623,8 +623,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteMaskProviderForIOOBE") static void storeMemorySegmentMaskIOOBE(IntFunction<$type$[]> fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask<$Boxtype$> vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java new file mode 100644 index 00000000000..7bb45bd6f79 --- /dev/null +++ b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2021, 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 + * @summary Test ThreadFlock with scoped values + * @enablePreview + * @modules java.base/jdk.internal.misc + * @modules jdk.incubator.concurrent + * @run testng WithScopedValue + */ + +import jdk.internal.misc.ThreadFlock; +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructureViolationException; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicReference; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class WithScopedValue { + + @DataProvider(name = "factories") + public Object[][] factories() { + var defaultThreadFactory = Executors.defaultThreadFactory(); + var virtualThreadFactory = Thread.ofVirtual().factory(); + return new Object[][]{ + { defaultThreadFactory, }, + { virtualThreadFactory, }, + }; + } + + /** + * Test inheritance of a scoped value. + */ + @Test(dataProvider = "factories") + public void testInheritsScopedValue(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "duke", () -> { + var result = new AtomicReference(); + try (var flock = ThreadFlock.open(null)) { + Thread thread = factory.newThread(() -> { + // child + result.set(name.get()); + }); + flock.start(thread); + } + return result.get(); + }); + assertEquals(value, "duke"); + } + + /** + * Test exiting a dynamic scope with open thread flocks. + */ + public void testStructureViolation1() { + ScopedValue name = ScopedValue.newInstance(); + class Box { + ThreadFlock flock1; + ThreadFlock flock2; + } + var box = new Box(); + try { + ScopedValue.where(name, "x1", () -> { + box.flock1 = ThreadFlock.open(null); + box.flock2 = ThreadFlock.open(null); + }); + fail(); + } catch (StructureViolationException expected) { } + assertTrue(box.flock1.isClosed()); + assertTrue(box.flock2.isClosed()); + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock1. + */ + public void testStructureViolation2() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock1.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertTrue(flock1.isClosed()); + assertTrue(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock2. + */ + public void testStructureViolation3() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock2.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertFalse(flock1.isClosed()); + assertTrue(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock3. + */ + public void testStructureViolation4() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock3.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertFalse(flock1.isClosed()); + assertFalse(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test start when a scoped value is bound after a thread flock is created. + */ + @Test(dataProvider = "factories") + public void testStructureViolation5(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var flock = ThreadFlock.open(null)) { + ScopedValue.where(name, "duke", () -> { + Thread thread = factory.newThread(() -> { }); + expectThrows(StructureViolationException.class, () -> flock.start(thread)); + }); + } + } + + /** + * Test start when a scoped value is re-bound after a thread flock is created. + */ + @Test(dataProvider = "factories") + public void testStructureViolation6(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue.where(name, "duke", () -> { + try (var flock = ThreadFlock.open(null)) { + ScopedValue.where(name, "duchess", () -> { + Thread thread = factory.newThread(() -> { }); + expectThrows(StructureViolationException.class, () -> flock.start(thread)); + }); + } + }); + } +} diff --git a/test/jdk/jdk/internal/platform/cgroup/TestCgroupMetrics.java b/test/jdk/jdk/internal/platform/cgroup/TestCgroupMetrics.java index d1f2c3932fb..a25f31da397 100644 --- a/test/jdk/jdk/internal/platform/cgroup/TestCgroupMetrics.java +++ b/test/jdk/jdk/internal/platform/cgroup/TestCgroupMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -36,16 +36,7 @@ public class TestCgroupMetrics { public static void main(String[] args) throws Exception { - // If cgroups is not configured, report success. - Metrics metrics = Metrics.systemMetrics(); - if (metrics == null) { - System.out.println("TEST PASSED!!!"); - return; - } - - MetricsTester metricsTester = new MetricsTester(); - metricsTester.testAll(metrics); - System.out.println("TEST PASSED!!!"); + MetricsTester.main(args); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index f1fc22e5e9b..854d24b2279 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -55,6 +55,7 @@ public static void main(String[] args) throws Exception { opts.addDockerOpts("--memory=256m"); opts.addJavaOpts("-cp", "/test-classes/"); opts.addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); + opts.addClassOptions("-incontainer"); DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); } finally { DockerTestUtils.removeDockerImage(imageName); diff --git a/test/jdk/jdk/internal/vm/Continuation/Basic.java b/test/jdk/jdk/internal/vm/Continuation/Basic.java index 8965c32fb75..5735a3301c4 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Basic.java +++ b/test/jdk/jdk/internal/vm/Continuation/Basic.java @@ -47,6 +47,7 @@ * @modules java.base/jdk.internal.vm * @build java.base/java.lang.StackWalkerHelper * +* @enablePreview * @run testng/othervm -XX:+VerifyStack -Xint Basic * @run testng/othervm -XX:+VerifyStack -Xcomp -XX:TieredStopAtLevel=3 -XX:CompileOnly=jdk/internal/vm/Continuation,Basic Basic * @run testng/othervm -XX:+VerifyStack -Xcomp -XX:-TieredCompilation -XX:CompileOnly=jdk/internal/vm/Continuation,Basic Basic diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index 3998891622f..77da319579f 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -72,6 +72,9 @@ import jdk.test.lib.Utils; import jdk.test.whitebox.WhiteBox; +import jdk.test.lib.Platform; +import jtreg.SkippedException; + public class Fuzz implements Runnable { static final boolean VERIFY_STACK = true; // could add significant time static final boolean FILE = true; @@ -84,6 +87,10 @@ public class Fuzz implements Runnable { static final Path TEST_DIR = Path.of(System.getProperty("test.src", ".")); public static void main(String[] args) { + if (Platform.isSlowDebugBuild() && Platform.isOSX() && Platform.isAArch64()) { + throw new SkippedException("Test is unstable with slowdebug bits " + + "on macosx-aarch64"); + } warmup(); for (int compileLevel : new int[]{4}) { for (boolean compileRun : new boolean[]{true}) { diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java b/test/jdk/jdk/internal/vm/TestTranslatedException.java similarity index 56% rename from test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java rename to test/jdk/jdk/internal/vm/TestTranslatedException.java index 57a505901a5..e17631595f9 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java +++ b/test/jdk/jdk/internal/vm/TestTranslatedException.java @@ -23,16 +23,12 @@ /* * @test - * @requires vm.jvmci - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open + * @modules java.base/jdk.internal.vm * java.base/jdk.internal.misc - * @library /compiler/jvmci/jdk.vm.ci.hotspot.test/src * @run testng/othervm - * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler - * jdk.vm.ci.hotspot.test.TestTranslatedException + * jdk.internal.vm.test.TestTranslatedException */ - -package jdk.vm.ci.hotspot.test; +package jdk.internal.vm.test; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -43,7 +39,7 @@ import org.testng.annotations.Test; import jdk.internal.misc.Unsafe; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.internal.vm.VMSupport; public class TestTranslatedException { @SuppressWarnings("serial") @@ -56,52 +52,37 @@ public Untranslatable(String message, Throwable cause) { @SuppressWarnings("unchecked") @Test public void encodeDecodeTest() throws Exception { - - Class translatedExceptionClass = Class.forName("jdk.vm.ci.hotspot.TranslatedException"); - - Method encode = translatedExceptionClass.getDeclaredMethod("encodeThrowable", Throwable.class); - Method decode = translatedExceptionClass.getDeclaredMethod("decodeThrowable", byte[].class); - encode.setAccessible(true); - decode.setAccessible(true); - Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); for (int i = 0; i < 10; i++) { throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); } - byte[] encoding = (byte[]) encode.invoke(null, throwable); - Throwable decoded = (Throwable) decode.invoke(null, encoding); - assertThrowableEquals(throwable, decoded); + encodeDecode(throwable); } - @SuppressWarnings("unchecked") @Test public void encodeDecodeTest2() throws Exception { + Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); + for (int i = 0; i < 10; i++) { + throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); + } + encodeDecode(throwable); + } + + private void encodeDecode(Throwable throwable) throws Exception { Unsafe unsafe = Unsafe.getUnsafe(); int bufferSize = 512; long buffer = 0L; while (true) { buffer = unsafe.allocateMemory(bufferSize); try { - Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); - for (int i = 0; i < 10; i++) { - throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); - } - - Method encode = HotSpotJVMCIRuntime.class.getDeclaredMethod("encodeThrowable", Throwable.class, long.class, int.class); - Method decode = HotSpotJVMCIRuntime.class.getDeclaredMethod("decodeAndThrowThrowable", long.class); - encode.setAccessible(true); - decode.setAccessible(true); - - int res = (Integer) encode.invoke(null, throwable, buffer, bufferSize); - + int res = VMSupport.encodeThrowable(throwable, buffer, bufferSize); if (res < 0) { bufferSize = -res; } else { try { - decode.invoke(null, buffer); + VMSupport.decodeAndThrowThrowable(buffer); throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); - } catch (InvocationTargetException e) { - Throwable decoded = e.getCause(); + } catch (Throwable decoded) { assertThrowableEquals(throwable, decoded); } return; @@ -117,12 +98,12 @@ private static void assertThrowableEquals(Throwable original, Throwable decoded) Assert.assertEquals(original == null, decoded == null); while (original != null) { if (Untranslatable.class.equals(original.getClass())) { - Assert.assertEquals("jdk.vm.ci.hotspot.TranslatedException", decoded.getClass().getName()); - Assert.assertEquals("jdk.vm.ci.hotspot.TranslatedException[jdk.vm.ci.hotspot.test.TestTranslatedException$Untranslatable]: test exception", decoded.toString()); - Assert.assertEquals("test exception", original.getMessage()); + Assert.assertEquals(decoded.getClass().getName(), "jdk.internal.vm.TranslatedException"); + Assert.assertEquals(decoded.toString(), "jdk.internal.vm.TranslatedException[jdk.internal.vm.test.TestTranslatedException$Untranslatable]: test exception"); + Assert.assertEquals(original.getMessage(), "test exception"); } else { - Assert.assertEquals(original.getClass().getName(), decoded.getClass().getName()); - Assert.assertEquals(original.getMessage(), decoded.getMessage()); + Assert.assertEquals(decoded.getClass().getName(), original.getClass().getName()); + Assert.assertEquals(decoded.getMessage(), original.getMessage()); } StackTraceElement[] originalStack = original.getStackTrace(); StackTraceElement[] decodedStack = decoded.getStackTrace(); @@ -130,12 +111,12 @@ private static void assertThrowableEquals(Throwable original, Throwable decoded) for (int i = 0, n = originalStack.length; i < n; ++i) { StackTraceElement originalStackElement = originalStack[i]; StackTraceElement decodedStackElement = decodedStack[i]; - Assert.assertEquals(originalStackElement.getClassLoaderName(), decodedStackElement.getClassLoaderName()); - Assert.assertEquals(originalStackElement.getModuleName(), decodedStackElement.getModuleName()); - Assert.assertEquals(originalStackElement.getClassName(), decodedStackElement.getClassName()); - Assert.assertEquals(originalStackElement.getMethodName(), decodedStackElement.getMethodName()); - Assert.assertEquals(originalStackElement.getFileName(), decodedStackElement.getFileName()); - Assert.assertEquals(originalStackElement.getLineNumber(), decodedStackElement.getLineNumber()); + Assert.assertEquals(decodedStackElement.getClassLoaderName(), originalStackElement.getClassLoaderName()); + Assert.assertEquals(decodedStackElement.getModuleName(), originalStackElement.getModuleName()); + Assert.assertEquals(decodedStackElement.getClassName(), originalStackElement.getClassName()); + Assert.assertEquals(decodedStackElement.getMethodName(), originalStackElement.getMethodName()); + Assert.assertEquals(decodedStackElement.getFileName(), originalStackElement.getFileName()); + Assert.assertEquals(decodedStackElement.getLineNumber(), originalStackElement.getLineNumber()); } original = original.getCause(); decoded = decoded.getCause(); diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java index 93b892880d6..8b3fbe88b90 100644 --- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java @@ -38,7 +38,7 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.api.consumer.recordingstream.TestClose + * @run main/othervm -Xlog:jfr+streaming+system=trace jdk.jfr.api.consumer.recordingstream.TestClose */ public class TestClose { diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java index 44e2b59680a..5cabd9e6884 100644 --- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java @@ -149,7 +149,7 @@ private static void testNestedStop() throws Exception { if (dumpOuter.size() != 3) { throw new AssertionError("Expected outer dump to have 3 events"); } - if (outerCount.get() == 3) { + if (outerCount.get() != 3) { throw new AssertionError("Expected outer stream to have 3 events"); } if (dumpInner.size() != 1) { diff --git a/test/jdk/jdk/jfr/api/consumer/streaming/TestJVMCrash.java b/test/jdk/jdk/jfr/api/consumer/streaming/TestJVMCrash.java index c1594462a80..be5acdddd75 100644 --- a/test/jdk/jdk/jfr/api/consumer/streaming/TestJVMCrash.java +++ b/test/jdk/jdk/jfr/api/consumer/streaming/TestJVMCrash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -43,7 +43,7 @@ public class TestJVMCrash { public static void main(String... args) throws Exception { int id = 1; while (true) { - try (TestProcess process = new TestProcess("crash-application-" + id++)) { + try (TestProcess process = new TestProcess("crash-application-" + id++, false /* createCore */)) { AtomicInteger eventCounter = new AtomicInteger(); try (EventStream es = EventStream.openRepository(process.getRepository())) { // Start from first event in repository diff --git a/test/jdk/jdk/jfr/api/consumer/streaming/TestProcess.java b/test/jdk/jdk/jfr/api/consumer/streaming/TestProcess.java index 4c03668cec2..8643ec35bc2 100644 --- a/test/jdk/jdk/jfr/api/consumer/streaming/TestProcess.java +++ b/test/jdk/jdk/jfr/api/consumer/streaming/TestProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -54,11 +54,16 @@ private static class TestEvent extends Event { private final Path path; public TestProcess(String name) throws IOException { + this(name, true /* createCore */); + } + + public TestProcess(String name, boolean createCore) throws IOException { this.path = Paths.get("action-" + System.currentTimeMillis()).toAbsolutePath(); String[] args = { "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:StartFlightRecording:settings=none", + "-XX:" + (createCore ? "+" : "-") + "CreateCoredumpOnCrash", TestProcess.class.getName(), path.toString() }; ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); diff --git a/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java b/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java index ffd3ef99174..0e4834ccfa1 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -52,6 +52,7 @@ public static void main(String[] args) throws Exception { System.out.println("Event:" + event); Events.assertField(event, "threadCount").atLeast(0); Events.assertField(event, "tieredCompilation"); + Events.assertField(event, "dynamicCompilerThreadCount"); } } } diff --git a/test/jdk/jdk/jfr/event/diagnostics/TestHeapDump.java b/test/jdk/jdk/jfr/event/diagnostics/TestHeapDump.java index a24e6d5996f..4cbb0826fa0 100644 --- a/test/jdk/jdk/jfr/event/diagnostics/TestHeapDump.java +++ b/test/jdk/jdk/jfr/event/diagnostics/TestHeapDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -65,6 +65,8 @@ public static void main(String[] args) throws Exception { Events.assertField(e, "gcBeforeDump").equal(true); Events.assertField(e, "onOutOfMemoryError").equal(false); Events.assertField(e, "size").equal(Files.size(path)); + Events.assertField(e, "compression").below(1); + Events.assertField(e, "overwrite").equal(false); System.out.println(e); } } diff --git a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java index 9f45bd8630f..afdb84952f4 100644 --- a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java +++ b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { Set eventNames= new HashSet<>(); for (EventType eventType : eventTypes) { verifyEventType(eventType); - verifyValueDesscriptors(eventType.getFields(), types); + verifyValueDescriptors(eventType.getFields(), types); System.out.println(); String eventName = eventType.getName(); if (eventNames.contains(eventName)) { @@ -116,11 +116,11 @@ public static void main(String[] args) throws Exception { } } - private static void verifyValueDesscriptors(List fields, Set visitedTypes) { + private static void verifyValueDescriptors(List fields, Set visitedTypes) { for (ValueDescriptor v : fields) { if (!visitedTypes.contains(v.getTypeName())) { visitedTypes.add(v.getTypeName()); - verifyValueDesscriptors(v.getFields(), visitedTypes); + verifyValueDescriptors(v.getFields(), visitedTypes); } verifyValueDescriptor(v); } diff --git a/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java new file mode 100644 index 00000000000..6495addbaec --- /dev/null +++ b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 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 jdk.jfr.event.runtime; + +import static jdk.test.lib.Asserts.assertGreaterThan; +import static jdk.test.lib.Asserts.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.opt.NativeMemoryTracking == null + * @requires vm.hasJFR + * @library /test/lib + * @modules jdk.jfr + * jdk.management + * @run main/othervm -XX:NativeMemoryTracking=summary -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestNativeMemoryUsageEvents true + * @run main/othervm -XX:NativeMemoryTracking=off -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestNativeMemoryUsageEvents false + */ +public class TestNativeMemoryUsageEvents { + private final static String UsageTotalEvent = EventNames.NativeMemoryUsageTotal; + private final static String UsageEvent = EventNames.NativeMemoryUsage; + + private final static int UsagePeriod = 1000; + private final static int K = 1024; + + private final static String[] UsageEventTypes = { + "Java Heap", + "Class", + "Thread", + "Thread Stack", + "Code", + "GC", + "GCCardSet", + "Compiler", + "JVMCI", + "Internal", + "Other", + "Symbol", + "Native Memory Tracking", + "Shared class space", + "Arena Chunk", + "Test", + "Tracing", + "Logging", + "Statistics", + "Arguments", + "Module", + "Safepoint", + "Synchronization", + "Serviceability", + "Metaspace", + "String Deduplication", + "Object Monitors" + }; + + private static ArrayList data = new ArrayList(); + + private static void generateHeapContents() { + for (int i = 0 ; i < 64; i++) { + for (int j = 0; j < K; j++) { + data.add(new byte[K]); + } + } + } + + private static void generateEvents(Recording recording) throws Exception { + // Enable the two types of events for "everyChunk", it will give + // an event at the beginning of the chunk as well as at the end. + recording.enable(UsageEvent).with("period", "everyChunk"); + recording.enable(UsageTotalEvent).with("period", "everyChunk"); + + recording.start(); + + // Generate data to force heap to grow. + generateHeapContents(); + + // To allow the two usage events to share a single NMTUsage snapshot + // there is an AgeThreshold set to 50ms and if the two events occur + // within this interval they will use the same snapshot. On fast + // machines it is possible that the whole heap contents generation + // take less than 50ms and therefor both beginChunk end endChunk + // events will use the same NMTUsage snapshot. To avoid this, do + // a short sleep. + Thread.sleep(100); + + recording.stop(); + } + + private static void verifyExpectedEventTypes(List events) throws Exception { + // First verify that the number of total usage events is greater than 0. + long numberOfTotal = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageTotalEvent)) + .count(); + + assertGreaterThan(numberOfTotal, 0L, "Should exist events of type: " + UsageTotalEvent); + + // Now verify that we got the expected events. + List uniqueEventTypes = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageEvent)) + .map(e -> e.getString("type")) + .distinct() + .toList(); + for (String type : UsageEventTypes) { + assertTrue(uniqueEventTypes.contains(type), "Events should include: " + type); + } + } + + private static void verifyHeapGrowth(List events) throws Exception { + List javaHeapCommitted = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageEvent)) + .filter(e -> e.getString("type").equals("Java Heap")) + .map(e -> e.getLong("committed")) + .toList(); + + // Verify that the heap has grown between the first and last sample. + long firstSample = javaHeapCommitted.get(0); + long lastSample = javaHeapCommitted.get(javaHeapCommitted.size() - 1); + assertGreaterThan(lastSample, firstSample, "heap should have grown and NMT should show that"); + } + + private static void verifyNoUsageEvents(List events) throws Exception { + Events.hasNotEvent(events, UsageEvent); + Events.hasNotEvent(events, UsageTotalEvent); + } + + public static void main(String[] args) throws Exception { + // The tests takes a single boolean argument that states wether or not + // it is run with -XX:NativeMemoryTracking=summary. When tracking is + // enabled the tests verifies that the correct events are sent and + // the other way around when turned off. + assertTrue(args.length == 1, "Must have a single argument"); + boolean nmtEnabled = Boolean.parseBoolean(args[0]); + + try (Recording recording = new Recording()) { + generateEvents(recording); + + var events = Events.fromRecording(recording); + if (nmtEnabled) { + verifyExpectedEventTypes(events); + verifyHeapGrowth(events); + } else { + verifyNoUsageEvents(events); + } + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestStop.java b/test/jdk/jdk/jfr/jmx/streaming/TestStop.java index b6825ec1626..83656cba8a7 100644 --- a/test/jdk/jdk/jfr/jmx/streaming/TestStop.java +++ b/test/jdk/jdk/jfr/jmx/streaming/TestStop.java @@ -158,7 +158,7 @@ private static void testNestedStop() throws Exception { if (dumpOuter.size() != 3) { throw new AssertionError("Expected outer dump to have 3 events"); } - if (outerCount.get() == 3) { + if (outerCount.get() != 3) { throw new AssertionError("Expected outer stream to have 3 events"); } if (dumpInner.size() != 1) { diff --git a/test/jdk/jdk/jfr/jvm/TestChunkIntegrity.java b/test/jdk/jdk/jfr/jvm/TestChunkIntegrity.java new file mode 100644 index 00000000000..0a192431811 --- /dev/null +++ b/test/jdk/jdk/jfr/jvm/TestChunkIntegrity.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 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 jdk.jfr.jvm; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedClassLoader; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordedStackTrace; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.jfr.TestClassLoader; + +/** + * @test + * @ignore + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jvm.TestChunkIntegrity + */ +public class TestChunkIntegrity { + + static abstract class StressThread extends Thread { + private volatile boolean keepAlive = true; + private final Random random = new Random(); + + public void run() { + try { + while (keepAlive) { + int count = random.nextInt(1_000) + 1; + for (int i = 0; i < count; i++) { + stress(); + } + System.out.println(count + " " + this.getClass().getName()); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + abstract protected void stress() throws Exception; + + public void kill() { + keepAlive = false; + try { + join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public static void main(String... args) throws Throwable { + Configuration c = Configuration.getConfiguration("profile"); + Path file = Path.of("recording.jfr"); + try (Recording r = new Recording(c)) { + r.start(); + List threads = new ArrayList<>(); + threads.add(new ClassStressor()); + threads.add(new ThreadStressor()); + threads.add(new StringStressor()); + threads.forEach(StressThread::start); + for (int i = 0; i < 10; i++) { + try (Recording t = new Recording()) { + t.start(); + } + } + threads.forEach(StressThread::kill); + r.dump(file); + + // Split recording file + Path directory = Path.of("disassembled"); + Files.createDirectories(directory); + disassemble(file, directory); + + // Verification + List full = RecordingFile.readAllEvents(file); + List chunkFiles = new ArrayList<>(Files.list(directory).toList()); + Collections.sort(chunkFiles); + int total = 0; + for (Path chunkFile : chunkFiles) { + System.out.println("Veryfying chunk: " + chunkFile + " " + total); + try (RecordingFile f = new RecordingFile(chunkFile)) { + int index = 0; + while (f.hasMoreEvents()) { + RecordedEvent event = f.readEvent(); + assertStressEvent(event, f, index); + assertEventEquals(full.get(total + index), event, index); + index++; + } + total += index; + } + } + System.out.println("Event count: " + total); + } + } + + static void assertStressEvent(RecordedEvent event, RecordingFile f, int index) throws IOException { + String name = event.getEventType().getName(); + if (name.equals("String") || name.equals("Thread") || name.equals("Clazz")) { + String fieldName = name.toLowerCase(); + Object value = event.getValue(fieldName); + if (value == null) { + writeFailureFile(f, index); + throw new AssertionError("Null found in " + name + " event. Event number " + index); + } + RecordedStackTrace stackTrace = event.getStackTrace(); + if (stackTrace == null) { + writeFailureFile(f, index); + throw new AssertionError("Stack trace was null. Event number " + index); + } + } + } + + private static void writeFailureFile(RecordingFile f, int index) throws IOException { + Path file = Path.of("failure.jfr"); + AtomicInteger count = new AtomicInteger(); + f.write(file, e-> count.incrementAndGet() == index + 1); + System.out.println("Failure file with only event " + index + " written to: " + file); + } + + static void assertEventEquals(RecordedEvent a, RecordedEvent b, int index) { + if (a.getEventType().getId() != b.getEventType().getId()) { + printRecordedObjects(a, b); + throw new AssertionError("Event types don't match. Event number " + index); + } + for (ValueDescriptor field : a.getEventType().getFields()) { + String n = field.getName(); + if (!isEqual(a.getValue(n), b.getValue(n))) { + printRecordedObjects(a, b); + throw new AssertionError("Events don't match. Event number " + index); + } + } + } + + private static void printRecordedObjects(RecordedObject a, RecordedObject b) { + System.out.println("Object A:"); + System.out.println(a); + System.out.println("Object B:"); + System.out.println(b); + } + + private static boolean isEqual(Object a, Object b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + System.out.println("One value null"); + System.out.println("Value A: " + a); + System.out.println("Value B: " + b); + return false; + } + if (a.getClass() != b.getClass()) { + System.out.println("Not same class"); + return false; + } + if (a instanceof Double d1 && b instanceof Double d2) { + return Double.doubleToRawLongBits(d1) == Double.doubleToRawLongBits(d2); + } + if (a instanceof Float f1 && b instanceof Float f2) { + return Float.floatToRawIntBits(f1) == Float.floatToRawIntBits(f2); + } + if (a instanceof String || a instanceof Number || a instanceof Boolean) { + return Objects.equals(a, b); + } + // Thread name may change, so sufficient to compare ID + if (a instanceof RecordedThread t1 && b instanceof RecordedThread t2) { + return t1.getId() == t2.getId(); + } + if (a instanceof RecordedObject r1 && b instanceof RecordedObject r2) { + for (ValueDescriptor field : r1.getFields()) { + String n = field.getName(); + if (!isEqual(r1.getValue(n), r2.getValue(n))) { + System.out.println("Field " + n + " doesn't match"); + System.out.println("Value A: " + r1.getValue(n)); + System.out.println("Value B: " + r2.getValue(n)); + return false; + } + } + return true; + } + if (a.getClass().isArray()) { + Object[] array = (Object[]) a; + Object[] brray = (Object[]) b; + if (array.length != brray.length) { + System.out.println("Array size doesn't match"); + return false; + } + for (int i = 0; i < array.length; i++) { + if (!isEqual(array[i], brray[i])) { + System.out.println("Array contents doesn't match"); + return false; + } + } + return true; + } + throw new AssertionError("Unknown object type " + a.getClass() + " found"); + } + + public static void disassemble(Path file, Path output) throws Throwable { + JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jfr"); + l.addToolArg("disassemble"); + l.addToolArg("--output"); + l.addToolArg(output.toAbsolutePath().toString()); + l.addToolArg("--max-chunks"); + l.addToolArg("1"); + l.addToolArg(file.toAbsolutePath().toString()); + ProcessTools.executeCommand(l.getCommand()); + } + + static class MyClass { + } + + static class ClassStressor extends StressThread { + @Name("Clazz") + static class ClassEvent extends Event { + Class clazz; + } + + @Override + protected void stress() throws Exception { + TestClassLoader loader = new TestClassLoader(); + Class clazz = loader.loadClass(MyClass.class.getName()); + if (clazz == null) { + throw new AssertionError("No class generated"); + } + ClassEvent e = new ClassEvent(); + e.clazz = clazz; + e.commit(); + } + } + + static class ThreadStressor extends StressThread { + @Name("Thread") + static class ThreadEvent extends Event { + Thread thread; + } + + @Override + protected void stress() throws Exception { + Thread t = new Thread(() -> { + ThreadEvent e = new ThreadEvent(); + e.thread = this; + e.commit(); + }); + t.start(); + t.join(); + } + } + + static class StringStressor extends StressThread { + @Name("String") + static class StringEvent extends Event { + String string; + } + + private long counter = 0; + + @Override + protected void stress() throws Exception { + String text = String.valueOf(counter) + "012345678901234567890"; + // Repeat string so characters are stored in check point event + for (int i = 0; i < 10; i++) { + StringEvent e = new StringEvent(); + e.string = text; + e.commit(); + } + counter++; + Thread.sleep(1); + } + } +} diff --git a/test/jdk/jdk/jfr/jvm/TestEventDuration.java b/test/jdk/jdk/jfr/jvm/TestEventDuration.java new file mode 100644 index 00000000000..53a7af9e323 --- /dev/null +++ b/test/jdk/jdk/jfr/jvm/TestEventDuration.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.jvm; + +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; +import java.nio.file.Path; + +/** + * @test Tests that the event duration is zero after a chunk rotation + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @modules jdk.jfr/jdk.jfr.internal + * @run main/othervm jdk.jfr.jvm.TestEventDuration + */ +public class TestEventDuration { + + static class InstantEvent extends Event { + long id; + } + + public static void main(String... args) throws Exception { + try (Recording r1 = new Recording()) { + r1.start(); + long counter = 0; + for (int i = 0; i < 10; i ++) { + try (Recording r2 = new Recording()) { + r2.start(); + InstantEvent e1 = new InstantEvent(); + e1.id = counter++; + e1.commit(); + InstantEvent e2 = new InstantEvent(); + e2.id = counter++; + e2.commit(); + } + } + Path p = Path.of("dump.jfr"); + r1.dump(p); + var events = RecordingFile.readAllEvents(p); + if (events.isEmpty()) { + throw new AssertionError("Expected at least one event"); + } + events.forEach(System.out::println); + for (var event : events) { + if (event.getDuration().toNanos() != 0) { + throw new AssertionError("Expected all events to have zero duration"); + } + } + } + } +} diff --git a/test/jdk/jdk/jfr/startupargs/TestStartDuration.java b/test/jdk/jdk/jfr/startupargs/TestStartDuration.java index 195f2362648..b610907bf84 100644 --- a/test/jdk/jdk/jfr/startupargs/TestStartDuration.java +++ b/test/jdk/jdk/jfr/startupargs/TestStartDuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,6 +25,7 @@ import java.time.Duration; +import jdk.jfr.FlightRecorder; import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.test.lib.Asserts; @@ -41,21 +42,38 @@ * @run main jdk.jfr.startupargs.TestStartDuration */ public class TestStartDuration { + public static final String RECORDING_NAME = "TestStartDuration"; + public static final String WAIT_FOR_RUNNING = "wait-for-running"; + public static final String WAIT_FOR_CLOSED = "wait-for-closed"; public static class TestValues { public static void main(String[] args) throws Exception { - Recording r = StartupHelper.getRecording("TestStartDuration"); - Asserts.assertEquals(r.getDuration(), Duration.parse(args[0])); - if (args.length > 1 && args[1].equals("wait")) { - CommonHelper.waitForRecordingState(r, RecordingState.STOPPED); + String action = args[0]; + Duration duration = Duration.parse(args[1]); + if (action.equals(WAIT_FOR_RUNNING)) { + Recording r = StartupHelper.getRecording("TestStartDuration"); + Asserts.assertEquals(r.getDuration(), duration); + CommonHelper.waitForRecordingState(r, RecordingState.RUNNING); + return; } + if (action.equals(WAIT_FOR_CLOSED)) { + while (!FlightRecorder.getFlightRecorder().getRecordings().isEmpty()) { + Thread.sleep(200); + System.out.println("A recording still running"); + } + return; + } + System.out.println("Unknown action: " + action); + System.exit(1); } } - private static void testDurationInRange(String duration, Duration durationString, boolean wait) throws Exception { + private static void testDurationInRange(String durationText, Duration duration, String action) throws Exception { ProcessBuilder pb = ProcessTools.createTestJvm( - "-XX:StartFlightRecording:name=TestStartDuration,duration=" + duration, TestValues.class.getName(), - durationString.toString(), wait ? "wait" : ""); + "-XX:StartFlightRecording:name=" + RECORDING_NAME + ",duration=" + durationText, + TestValues.class.getName(), + action, + duration.toString()); OutputAnalyzer out = ProcessTools.executeProcess(pb); out.shouldHaveExitValue(0); @@ -84,12 +102,13 @@ private static void testDurationOutOfRange(String duration) throws Exception { } public static void main(String[] args) throws Exception { - testDurationInRange("1s", Duration.ofSeconds(1), true); - testDurationInRange("1234003005ns", Duration.ofNanos(1234003005L), true); - testDurationInRange("1034ms", Duration.ofMillis(1034), false); - testDurationInRange("32m", Duration.ofMinutes(32), false); - testDurationInRange("65h", Duration.ofHours(65), false); - testDurationInRange("354d", Duration.ofDays(354), false); + testDurationInRange("1s", Duration.ofSeconds(1), WAIT_FOR_CLOSED); + testDurationInRange("1234003005ns", Duration.ofNanos(1234003005L), WAIT_FOR_CLOSED); + testDurationInRange("1034ms", Duration.ofMillis(1034), WAIT_FOR_CLOSED); + testDurationInRange("3500s", Duration.ofSeconds(3500), WAIT_FOR_RUNNING); + testDurationInRange("59m", Duration.ofMinutes(59), WAIT_FOR_RUNNING); + testDurationInRange("65h", Duration.ofHours(65), WAIT_FOR_RUNNING); + testDurationInRange("354d", Duration.ofDays(354), WAIT_FOR_RUNNING); // additional test for corner values, verify that JVM accepts following durations testDurationInRangeAccept("1000000000ns"); diff --git a/test/jdk/jdk/jfr/tool/TestPrintXML.java b/test/jdk/jdk/jfr/tool/TestPrintXML.java index d32dc3236ae..c8d60166d4c 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintXML.java +++ b/test/jdk/jdk/jfr/tool/TestPrintXML.java @@ -132,6 +132,8 @@ static boolean compare(Object eventObject, Object xmlObject) { Map xmlMap = (Map) xmlObject; List fields = re.getFields(); if (fields.size() != xmlMap.size()) { + System.err.println("Size of fields of recorded object (" + fields.size() + + ") and reference (" + xmlMap.size() + ") differ"); return false; } for (ValueDescriptor v : fields) { @@ -154,6 +156,7 @@ static boolean compare(Object eventObject, Object xmlObject) { expectedValue = Long.toUnsignedString(re.getLong(name)); } if (!compare(expectedValue, xmlValue)) { + System.err.println("Expcted value " + expectedValue + " differs from " + xmlValue); return false; } } @@ -163,10 +166,14 @@ static boolean compare(Object eventObject, Object xmlObject) { Object[] array = (Object[]) eventObject; Object[] xmlArray = (Object[]) xmlObject; if (array.length != xmlArray.length) { + System.err.println("Array length " + array.length + " differs from length " + + xmlArray.length); return false; } for (int i = 0; i < array.length; i++) { if (!compare(array[i], xmlArray[i])) { + System.err.println("Array element " + i + "(" + array[i] + + ") differs from element " + xmlArray[i]); return false; } } @@ -174,7 +181,11 @@ static boolean compare(Object eventObject, Object xmlObject) { } String s1 = String.valueOf(eventObject); String s2 = (String) xmlObject; - return s1.equals(s2); + boolean res = s1.equals(s2); + if (! res) { + System.err.println("Event object string " + s1 + " differs from " + s2); + } + return res; } static class XMLEvent { diff --git a/test/jdk/jdk/nio/zipfs/ZipFSTester.java b/test/jdk/jdk/nio/zipfs/ZipFSTester.java index 08c998ca221..64362d263ab 100644 --- a/test/jdk/jdk/nio/zipfs/ZipFSTester.java +++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -33,6 +33,7 @@ import java.nio.channels.SeekableByteChannel; import java.nio.file.DirectoryStream; import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.FileSystemAlreadyExistsException; import java.nio.file.FileSystemException; @@ -45,6 +46,7 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttributeView; import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; import java.util.Arrays; @@ -73,7 +75,7 @@ * @test * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596 * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211 - * 8131067 8034802 8210899 8273961 8271079 + * 8131067 8034802 8210899 8273961 8271079 8299864 * @summary Test Zip filesystem provider * @modules jdk.zipfs * @run main ZipFSTester @@ -92,7 +94,8 @@ public static void main(String[] args) throws Exception { try (FileSystem fs = newZipFileSystem(jarFile, Collections.emptyMap())) { test0(fs); test1(fs); - test2(fs); // more tests + test2(fs); + testFileStoreNullArgs(fs); // more tests } testStreamChannel(); testTime(jarFile); @@ -100,7 +103,7 @@ public static void main(String[] args) throws Exception { test8131067(); } - private static Random rdm = new Random(); + private static final Random RDM = new Random(); static void test0(FileSystem fs) throws Exception @@ -131,7 +134,7 @@ static void test1(FileSystem fs0) String tmpName = src.toString(); try (OutputStream os = Files.newOutputStream(src)) { byte[] bits = new byte[12345]; - rdm.nextBytes(bits); + RDM.nextBytes(bits); os.write(bits); } @@ -182,8 +185,8 @@ static void test1(FileSystem fs0) checkEqual(src, dst); // copy - Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) + - "/efg" + rdm.nextInt(100) + "/foo.class"); + Path dst2 = getPathWithParents(fs, "/xyz" + RDM.nextInt(100) + + "/efg" + RDM.nextInt(100) + "/foo.class"); Files.copy(dst, dst2); //dst.moveTo(dst2); checkEqual(src, dst2); @@ -360,7 +363,7 @@ public void run() { z2zmove(fs2, fs3, path); itr.remove(); } - } catch (FileAlreadyExistsException x){ + } catch (FileAlreadyExistsException x) { itr.remove(); } catch (Exception x) { x.printStackTrace(); @@ -419,7 +422,7 @@ public void run() { static final int METHOD_DEFLATED = 8; static Object[][] getEntries() { - Object[][] entries = new Object[10 + rdm.nextInt(20)][3]; + Object[][] entries = new Object[10 + RDM.nextInt(20)][3]; // first entries shall test the corner case of 0 bytes of data entries[0][0] = "entries" + 0; entries[0][1] = METHOD_STORED; @@ -430,10 +433,10 @@ static Object[][] getEntries() { // the rest is random data for (int i = 2; i < entries.length; i++) { entries[i][0] = "entries" + i; - entries[i][1] = rdm.nextInt(10) % 2 == 0 ? - METHOD_STORED : METHOD_DEFLATED; - entries[i][2] = new byte[rdm.nextInt(8192)]; - rdm.nextBytes((byte[])entries[i][2]); + entries[i][1] = RDM.nextInt(10) % 2 == 0 ? + METHOD_STORED : METHOD_DEFLATED; + entries[i][2] = new byte[RDM.nextInt(8192)]; + RDM.nextBytes((byte[]) entries[i][2]); } return entries; } @@ -494,8 +497,8 @@ private static void checkRead(Path path, byte[] expected) throws IOException { int pos = 0; int len = 0; if (expected.length > 0) { - pos = rdm.nextInt((int) sbc.size()); - len = rdm.nextInt(Math.min(buf.length, expected.length - pos)); + pos = RDM.nextInt((int) sbc.size()); + len = RDM.nextInt(Math.min(buf.length, expected.length - pos)); } // System.out.printf(" --> %d, %d%n", pos, len); bb.position(0).limit(len); // bb.flip().limit(len); @@ -932,8 +935,8 @@ private static void checkEqual(Path src, Path dst) throws IOException // Check position(x) + read() at the specific pos/len for (int i = 0; i < 10; i++) { - int pos = rdm.nextInt((int)chSrc.size()); - int limit = rdm.nextInt(1024); + int pos = RDM.nextInt((int) chSrc.size()); + int limit = RDM.nextInt(1024); if (chSrc.position(pos).position() != chDst.position(pos).position()) { System.out.printf("dst/src.position(pos failed%n"); } @@ -1079,4 +1082,42 @@ static Path getPathWithParents(FileSystem fs, String name) mkdirs(parent); return path; } + + /** + * Tests if certain methods throw a NullPointerException if invoked with null + * as specified in java.nio.file.package-info.java + * @param fs file system containing at least one ZipFileStore + * + * @see 8299864 + */ + static void testFileStoreNullArgs(FileSystem fs) { + FileStore store = fs.getFileStores().iterator().next(); + + // Make sure we are testing the right thing + if (!"jdk.nio.zipfs.ZipFileStore".equals(store.getClass().getName())) + throw new AssertionError(store.getClass().getName()); + + assertThrowsNPE(() -> store.supportsFileAttributeView((String) null)); + assertThrowsNPE(() -> store.supportsFileAttributeView((Class) null)); + assertThrowsNPE(() -> store.getAttribute(null)); + assertThrowsNPE(() -> store.getFileStoreAttributeView(null)); + } + + @FunctionalInterface + private interface ThrowingRunnable { + void run() throws Exception; + } + + static void assertThrowsNPE(ThrowingRunnable r) { + try { + r.run(); + // Didn't throw an exception + throw new AssertionError(); + } catch (NullPointerException expected) { + // happy path + } catch (Exception e) { + throw new AssertionError(e); + } + } + } diff --git a/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java b/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java index b769c6d8268..4cc16e53e71 100644 --- a/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java @@ -52,7 +52,7 @@ /* * @test * @key headful screenshots - * @summary Verifies SwingSet3 EditorPaneDemo by navigating and and validating + * @summary Verifies SwingSet3 EditorPaneDemo by navigating and validating * the page contents in all pages * * @library /sanity/client/lib/jemmy/src diff --git a/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java b/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java index 4462bf2e12d..d6d9469c589 100644 --- a/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java @@ -272,8 +272,8 @@ private void initializeSelectWithPreviewDialog() { fileChooser = new JFileChooserOperator(); fileChooserDialog = new JDialogOperator(OPEN); String openButtonText = OPEN; - // In GTK and Motif L&F, open button text is 'OK' - if (LookAndFeel.isMotif() || LookAndFeel.isGTK()) { + // In Motif L&F, open button text is 'OK' + if (LookAndFeel.isMotif()) { openButtonText = OK; } openButton = new JButtonOperator(fileChooser, openButtonText); diff --git a/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java b/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java index 6b7b270173f..0e80df72a63 100644 --- a/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java @@ -39,7 +39,7 @@ * @test * @key headful * @summary Verifies SwingSet3 TabbedPaneDemo by iterating through tab placement - * positions, opening each tab and verifying the the tab gets selected. + * positions, opening each tab and verifying the tab gets selected. * * @library /sanity/client/lib/jemmy/src * @library /sanity/client/lib/Extensions/src diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties index 77c6f82fc1e..3d584efb05a 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties @@ -1,6 +1,6 @@ ### Tree Demo ### -TreeDemo.accessible_description=This demo shows shows a sample usage of a JTree component. +TreeDemo.accessible_description=This demo shows a sample usage of a JTree component. TreeDemo.tooltip=JTree demo TreeDemo.name=Tree Demo TreeDemo.music=Music diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java index c7b27be0895..0e2c6866fd0 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java @@ -286,7 +286,7 @@ public Window waitWindow(Window o, ComponentChooser ch) } /** - * Wait till the count of windows which meet the the search criteria becomes + * Wait till the count of windows which meet the search criteria becomes * equal to count. * * @param ch a component chooser used to define and apply the search @@ -300,7 +300,7 @@ public static void waitWindowCount(ComponentChooser ch, int count) } /** - * Wait till the count of windows which meet the the search criteria becomes + * Wait till the count of windows which meet the search criteria becomes * equal to count. * * @param owner The owner window of all the windows to be checked diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java index 99a076b7b4d..4575c4dbe98 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java @@ -252,7 +252,7 @@ public ComponentOperator(ContainerOperator cont, int index) { /** * Constructor. Waits for a component in a container to show. The component - * is is the first {@code java.awt.Component} that shows and that lies + * is the first {@code java.awt.Component} that shows and that lies * below the container in the display containment hierarchy. Uses cont's * timeout and output for waiting and to init operator. * diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java index e97862832e2..29d7c238b79 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java @@ -66,7 +66,7 @@ *

    Timeouts used:
    * JTreeOperator.WaitNodeExpandedTimeout - time to wait node expanded
    * JTreeOperator.WaitNodeCollapsedTimeout - time to wait node collapsed
    - * JTreeOperator.WaitAfterNodeExpandedTimeout - time to to sleep after node + * JTreeOperator.WaitAfterNodeExpandedTimeout - time to sleep after node * expanded
    * JTreeOperator.WaitNextNodeTimeout - time to wait next node displayed
    * JTreeOperator.WaitNodeVisibleTimeout - time to wait node visible
    diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java index 840362b73bd..e29bf9b116b 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java @@ -366,7 +366,7 @@ public Timeouts getTimeouts() { } /** - * Returns component visualizer. Visualizer is used from from + * Returns component visualizer. Visualizer is used from * makeComponentVisible() method. * * @return a visualizer assigned to this operator. @@ -378,7 +378,7 @@ public ComponentVisualizer getVisualizer() { } /** - * Changes component visualizer. Visualizer is used from from + * Changes component visualizer. Visualizer is used from * makeComponentVisible() method. * * @param vo a visualizer to assign to this operator. @@ -1080,7 +1080,7 @@ public String map() { } /** - * Interface used to make component visible & ready to to make operations + * Interface used to make component visible & ready to make operations * with. */ public interface ComponentVisualizer { diff --git a/test/jdk/sun/invoke/util/ValueConversionsTest.java b/test/jdk/sun/invoke/util/ValueConversionsTest.java index 9a936cc97ff..23e70f31c96 100644 --- a/test/jdk/sun/invoke/util/ValueConversionsTest.java +++ b/test/jdk/sun/invoke/util/ValueConversionsTest.java @@ -134,30 +134,6 @@ public void testBox() throws Throwable { } } - @Test - public void testCast() throws Throwable { - Class[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class }; - Object[] objects = { new Object(), Boolean.FALSE, "hello", (Long)12L, (Integer)6 }; - for (Class dst : types) { - MethodHandle caster = ValueConversions.cast().bindTo(dst); - assertEquals(caster.type(), MethodHandles.identity(Object.class).type()); - for (Object obj : objects) { - Class src = obj.getClass(); - boolean canCast = dst.isAssignableFrom(src); - try { - Object result = caster.invokeExact(obj); - if (canCast) - assertEquals(obj, result); - else - assertEquals("cast should not have succeeded", dst, obj); - } catch (ClassCastException ex) { - if (canCast) - throw ex; - } - } - } - } - @Test public void testConvert() throws Throwable { for (long tval = 0, ctr = 0;;) { diff --git a/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java b/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java deleted file mode 100644 index 27d54af6a0b..00000000000 --- a/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @key headful - * @bug 8275715 - * @summary Tests that paint method is not called twice - * @run main/othervm MultiPaintEventTest - */ - -import java.awt.*; - -public class MultiPaintEventTest extends Canvas { - - private int count = 0; - private final Object lock = new Object(); - - public void paint(Graphics g) { - synchronized(lock) { - count++; - } - - int w = getWidth(); - int h = getHeight(); - - Graphics2D g2d = (Graphics2D)g; - if (count % 2 == 1) { - g2d.setColor(Color.green); - } else { - g2d.setColor(Color.red); - } - g2d.fillRect(0, 0, w, h); - } - - public int getCount() { - synchronized(lock) { - return count; - } - } - - public Dimension getPreferredSize() { - return new Dimension(400, 400); - } - - public static void main(String[] args) { - MultiPaintEventTest test = new MultiPaintEventTest(); - Frame frame = new Frame(); - frame.setUndecorated(true); - frame.add(test); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - - try { - Thread.sleep(2000); - if (test.getCount() > 1) { - throw new RuntimeException("Processed unnecessary paint()."); - } - } catch (InterruptedException ex) { - throw new RuntimeException("Failed: Interrupted"); - } finally { - frame.dispose(); - } - } -} diff --git a/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java b/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java index 9e0194b4985..9c5cf3de2e3 100644 --- a/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java +++ b/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java @@ -75,7 +75,7 @@ private static void testInvalidType(AccelSurface surface, int type) { if (ret != 0l) { System.err.printf( "FAILED: surface.getNativeResource(%d) returned" + - " 0x%s. It should have have returned 0L\n", + " 0x%s. It should have returned 0L\n", type, ret); failed = true; } diff --git a/test/jdk/sun/jvmstat/testlibrary/utils.sh b/test/jdk/sun/jvmstat/testlibrary/utils.sh index d0224a293d3..a08ae37a99d 100644 --- a/test/jdk/sun/jvmstat/testlibrary/utils.sh +++ b/test/jdk/sun/jvmstat/testlibrary/utils.sh @@ -178,7 +178,7 @@ kill_proc_common() { # check if it's still hanging around if [ $? -eq 0 ] then - # it's still lingering, now it it hard + # it's still lingering, now hit it hard kill -KILL ${kpid} 2>/dev/null if [ $? -ne 0 ] then diff --git a/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java b/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java index 5fb1fab4eb4..ab029b26268 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java @@ -165,7 +165,7 @@ public void run() { if (testFailed) { int exitValue = output.getExitValue(); if (needRetry) { - System.err.println("Test FAILURE on " + name + " reason: run out of retries to to pick free ports"); + System.err.println("Test FAILURE on " + name + " reason: run out of retries to pick free ports"); } else if (exitValue == COMMUNICATION_ERROR_EXIT_VAL) { // Failure case since the java processes should still be // running. diff --git a/test/jdk/sun/misc/SunMiscSignalTest.java b/test/jdk/sun/misc/SunMiscSignalTest.java index dd45ec179b0..ff88ccf2485 100644 --- a/test/jdk/sun/misc/SunMiscSignalTest.java +++ b/test/jdk/sun/misc/SunMiscSignalTest.java @@ -95,7 +95,7 @@ static void setup() { // Provider of signals to be tested with variations for -Xrs and // platform dependencies - // -Xrs restricted signals signals the VM will not handle SIGINT, SIGTERM, SIGHUP and others + // -Xrs restricted signals the VM will not handle SIGINT, SIGTERM, SIGHUP and others @DataProvider(name = "supportedSignals") static Object[][] supportedSignals() { RestrictedSignals rs = RUNNING_WITH_Xrs ? RestrictedSignals.XRS : RestrictedSignals.NORMAL; diff --git a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java deleted file mode 100644 index 38c00e68c87..00000000000 --- a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 4333920 4994372 - * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem - * @modules java.base/sun.net - * jdk.httpserver - * @library /test/lib - * @run main ChunkedEncodingWithProgressMonitorTest - */ - -import java.net.*; -import java.util.BitSet; -import sun.net.ProgressMeteringPolicy; -import sun.net.ProgressMonitor; -import sun.net.ProgressListener; -import sun.net.ProgressEvent; - -public class ChunkedEncodingWithProgressMonitorTest { - public static void main (String[] args) throws Exception { - ProgressMonitor.setMeteringPolicy(new MyProgressMeteringPolicy()); - ProgressListener listener = new MyProgressListener(); - ProgressMonitor.getDefault().addProgressListener(listener); - ChunkedEncodingTest.test(); - ProgressMonitor.getDefault().removeProgressListener(listener); - - if (flag.cardinality() != 3) { - throw new RuntimeException("All three methods in ProgressListener"+ - " should be called. Yet the number of"+ - " methods actually called are "+ - flag.cardinality()); - } - } - - static class MyProgressMeteringPolicy implements ProgressMeteringPolicy { - /** - * Return true if metering should be turned on for a particular network input stream. - */ - public boolean shouldMeterInput(URL url, String method) { - return true; - } - - /** - * Return update notification threshold. - */ - public int getProgressUpdateThreshold() { - return 8192; - } - } - - static BitSet flag = new BitSet(3); - - static class MyProgressListener implements ProgressListener { - /** - * Start progress. - */ - public void progressStart(ProgressEvent evt) { - System.out.println("start: received progressevent "+evt); - if (flag.nextSetBit(0) == -1) - flag.set(0); - } - - /** - * Update progress. - */ - public void progressUpdate(ProgressEvent evt) { - System.out.println("update: received progressevent "+evt); - if (flag.nextSetBit(1) == -1) - flag.set(1); - } - - /** - * Finish progress. - */ - public void progressFinish(ProgressEvent evt) { - System.out.println("finish: received progressevent "+evt); - if (flag.nextSetBit(2) == -1) - flag.set(2); - } - } -} diff --git a/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java b/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java index 6ba25724123..c96df382017 100644 --- a/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java +++ b/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java @@ -63,18 +63,28 @@ public void close() { } catch (IOException e) {} } - static void readRequest(Socket s) throws IOException { - InputStream is = s.getInputStream(); - is.read(); - while (is.available() > 0) - is.read(); + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; + + // Read until the end of a HTTP request + static void readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + break; + } + } else { + requestEndCount = 0; + } + } } public void run() { try { while (true) { s = serverSocket.accept(); - readRequest(s); + readOneRequest(s.getInputStream()); OutputStream os = s.getOutputStream(); String resp = "" + "HTTP/1.1 200 OK\r\n" + @@ -87,7 +97,10 @@ public void run() { os.flush(); InputStream is = s.getInputStream(); long l1 = System.currentTimeMillis(); - is.read(); + int readResult = is.read(); + if (readResult != -1) { + System.out.println("Unexpected byte received: " + readResult); + } long l2 = System.currentTimeMillis(); long diff = (l2 - l1) / 1000; /* diff --git a/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java new file mode 100644 index 00000000000..16325c893c8 --- /dev/null +++ b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 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 8240275 + * @library /test/lib + * @run main/othervm KeepAliveStreamFinalizer + * @summary HttpsURLConnection: connection must not be reused after finalization + */ + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.net.UnknownHostException; + +public class KeepAliveStreamFinalizer { + + static Server server; + private static volatile String failureReason; + + static class Server extends Thread { + final ServerSocket srv; + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n'}; + + Server(ServerSocket s) { + srv = s; + } + + boolean readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + return true; + } + } else { + requestEndCount = 0; + } + } + return false; + } + + public void run() { + try { + while (true) { + Socket ss = srv.accept(); + Thread t1 = new Thread(new Runnable() { + public void run() { + try { + InputStream in = ss.getInputStream(); + OutputStream out = ss.getOutputStream(); + while (readOneRequest(in)) { + out.write("HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Length: 1\r\n\r\na".getBytes()); + out.flush(); + } + in.close(); + out.close(); + ss.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + t1.setDaemon(true); + t1.start(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) throws Exception { + InetSocketAddress address = startHttpServer(); + clientHttpCalls(address); + if (failureReason != null) { + throw new RuntimeException(failureReason); + } + } + + public static InetSocketAddress startHttpServer() throws Exception { + InetAddress localHost = InetAddress.getLoopbackAddress(); + InetSocketAddress address = new InetSocketAddress(localHost, 0); + ServerSocket serverSocket = new ServerSocket(); + serverSocket.bind(address); + server = new Server(serverSocket); + server.setDaemon(true); + server.start(); + return (InetSocketAddress) serverSocket.getLocalSocketAddress(); + } + + public static void doRequest(URL url) throws IOException { + HttpsURLConnection c = (HttpsURLConnection)url.openConnection(); + c.setRequestMethod("POST"); + c.setDoOutput(true); + OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream()); + out.write("test"); + out.close(); + int responseCode = c.getResponseCode(); + // Fully reading the body causes the HttpsClient to be added to the KeepAliveCache immediately, + // which avoids this issue since GC will not finalize the HttpsClient. + } + + public static void clientHttpCalls(InetSocketAddress address) throws Exception { + try { + System.err.println("http server listen on: " + address.getPort()); + String hostAddr = address.getAddress().getHostAddress(); + if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]"; + String baseURLStr = "https://" + hostAddr + ":" + address.getPort() + "/"; + + URL testUrl = new URL(baseURLStr); + + // CheckFinalizeSocketFactory is not a real SSLSocketFactory; + // it produces regular non-SSL sockets. Effectively, the request + // is made over http. + HttpsURLConnection.setDefaultSSLSocketFactory(new CheckFinalizeSocketFactory()); + // now perform up to 3 requests; with the broken KeepAliveStream finalizer, + // the second request usually attempts to use a finalized socket + for (int i = 0; i < 3; i++) { + System.err.println("Request #" + (i + 1)); + doRequest(testUrl); + System.gc(); + Thread.sleep(100); + if (failureReason != null) break; + } + } finally { + server.srv.close(); + } + } + + static class CheckFinalizeSocket extends SSLSocket { + private volatile boolean finalized; + public void finalize() throws Throwable { + System.err.println("In finalize"); + super.finalize(); + finalized = true; + } + + @Override + public InputStream getInputStream() throws IOException { + if (finalized) { + System.err.println(failureReason = "getInputStream called after finalize"); + Thread.dumpStack(); + } + return super.getInputStream(); + } + + @Override + public OutputStream getOutputStream() throws IOException { + if (finalized) { + System.err.println(failureReason = "getOutputStream called after finalize"); + Thread.dumpStack(); + } + return super.getOutputStream(); + } + + @Override + public synchronized void close() throws IOException { + if (finalized) { + System.err.println(failureReason = "close called after finalize"); + Thread.dumpStack(); + } + super.close(); + } + + // required abstract method overrides + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public String[] getEnabledCipherSuites() { + return new String[0]; + } + @Override + public void setEnabledCipherSuites(String[] suites) { } + @Override + public String[] getSupportedProtocols() { + return new String[0]; + } + @Override + public String[] getEnabledProtocols() { + return new String[0]; + } + @Override + public void setEnabledProtocols(String[] protocols) { } + @Override + public SSLSession getSession() { + return null; + } + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void startHandshake() throws IOException { } + @Override + public void setUseClientMode(boolean mode) { } + @Override + public boolean getUseClientMode() { + return false; + } + @Override + public void setNeedClientAuth(boolean need) { } + @Override + public boolean getNeedClientAuth() { + return false; + } + @Override + public void setWantClientAuth(boolean want) { } + @Override + public boolean getWantClientAuth() { + return false; + } + @Override + public void setEnableSessionCreation(boolean flag) { } + @Override + public boolean getEnableSessionCreation() { + return false; + } + } + + static class CheckFinalizeSocketFactory extends SSLSocketFactory { + + @Override + public Socket createSocket() throws IOException { + return new CheckFinalizeSocket(); + } + // required abstract method overrides + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String[] getDefaultCipherSuites() { + return new String[0]; + } + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + throw new UnsupportedOperationException(); + } + } +} + diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java b/test/jdk/sun/security/pkcs/pkcs7/NewSigAlg.java similarity index 51% rename from test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java rename to test/jdk/sun/security/pkcs/pkcs7/NewSigAlg.java index 3f27782ea5b..098dd9caaa4 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java +++ b/test/jdk/sun/security/pkcs/pkcs7/NewSigAlg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,31 +21,31 @@ * questions. */ -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.io.InputStream; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; -import java.util.function.Supplier; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfInputStream - extends FlowPublisherVerification { +/* + * @test + * @bug 8299746 + * @summary Accept unknown signatureAlgorithm in PKCS7 SignerInfo + * @modules java.base/sun.security.pkcs + * java.base/sun.security.x509 + * @library /test/lib + */ - public BodyPublishersOfInputStream() { - super(new TestEnvironment(450L)); - } +import jdk.test.lib.Asserts; +import sun.security.pkcs.SignerInfo; +import sun.security.x509.AlgorithmId; - @Override - public Publisher createFlowPublisher(long nElements) { - Supplier s = () -> S.inputStreamOfNReads((int) nElements); - return BodyPublishers.ofInputStream(s); +public class NewSigAlg { + public static void main(String[] args) throws Exception { + test("SHA-1", "RSA", "SHA1withRSA"); + test("SHA-1", "SHA1withRSA", "SHA1withRSA"); + test("SHA-1", "SHA256withRSA", "SHA1withRSA"); + // Sorry I have to use something that has an OID but not known + // as a signature algorithm. + test("SHA-1", "PBES2", "PBES2"); } - @Override - public Publisher createFailedFlowPublisher() { - return null; + static void test(String d, String e, String s) throws Exception { + Asserts.assertEQ(s, SignerInfo.makeSigAlg( + AlgorithmId.get(d), AlgorithmId.get(s), false)); } } diff --git a/test/jdk/sun/security/provider/PolicyFile/Comparator.Combined.Policy b/test/jdk/sun/security/provider/PolicyFile/Comparator.Combined.Policy deleted file mode 100644 index 3db6a34f785..00000000000 --- a/test/jdk/sun/security/provider/PolicyFile/Comparator.Combined.Policy +++ /dev/null @@ -1,33 +0,0 @@ - -// should be granted -grant principal com.sun.security.auth.UnixPrincipal "1", - principal Comparator$PCompare2 "2" { - permission java.util.PropertyPermission "foo", "read"; -}; - -// should be granted -grant principal Comparator$PCompare1 "1", - principal com.sun.security.auth.NTUserPrincipal "4" { - permission java.util.PropertyPermission "bar", "read"; -}; - -// should be granted -grant principal com.sun.security.auth.UnixPrincipal "1", - principal javax.security.auth.x500.X500Principal "cn=x500", - principal Comparator$PCompare2 "2" { - permission java.util.PropertyPermission "hello", "read"; -}; - -// should be granted -grant principal Comparator$PCompare1 "1", - principal com.sun.security.auth.NTUserPrincipal "4", - principal javax.security.auth.x500.X500Principal "cn=x500" { - permission java.util.PropertyPermission "world", "read"; -}; - -// should not be granted -grant principal Comparator$PCompare1 "1", - principal Comparator$PCompare3 "3" { - permission java.util.PropertyPermission "foobar", "read"; -}; - diff --git a/test/jdk/sun/security/provider/PolicyFile/Comparator.Comparator.Policy b/test/jdk/sun/security/provider/PolicyFile/Comparator.Comparator.Policy deleted file mode 100644 index d0357c27613..00000000000 --- a/test/jdk/sun/security/provider/PolicyFile/Comparator.Comparator.Policy +++ /dev/null @@ -1,18 +0,0 @@ - -// should be granted -grant principal Comparator$PCompare1 "1" { - permission java.util.PropertyPermission "foo", "read"; -}; - -// should be granted -grant principal Comparator$PCompare1 "1", - principal Comparator$PCompare2 "2" { - permission java.util.PropertyPermission "bar", "read"; -}; - -// should not be granted -grant principal Comparator$PCompare1 "1", - principal Comparator$PCompare3 "3" { - permission java.util.PropertyPermission "foobar", "read"; -}; - diff --git a/test/jdk/sun/security/provider/PolicyFile/Comparator.Principal.Policy b/test/jdk/sun/security/provider/PolicyFile/Comparator.Principal.Policy deleted file mode 100644 index f837f8c25ff..00000000000 --- a/test/jdk/sun/security/provider/PolicyFile/Comparator.Principal.Policy +++ /dev/null @@ -1,18 +0,0 @@ - -// should be granted -grant principal com.sun.security.auth.UnixPrincipal "1" { - permission java.util.PropertyPermission "foo", "read"; -}; - -// should be granted -grant principal javax.security.auth.x500.X500Principal "cn=2", - principal com.sun.security.auth.NTUserPrincipal "2" { - permission java.util.PropertyPermission "bar", "read"; -}; - -// should not be granted -grant principal javax.security.auth.x500.X500Principal "cn=2", - principal com.sun.security.auth.UnixPrincipal "1" { - permission java.util.PropertyPermission "foobar", "read"; -}; - diff --git a/test/jdk/sun/security/provider/PolicyFile/Comparator.java b/test/jdk/sun/security/provider/PolicyFile/Comparator.java deleted file mode 100644 index 07a9c44cecd..00000000000 --- a/test/jdk/sun/security/provider/PolicyFile/Comparator.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. - * 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 5037004 - * @summary Frivolous ClassCastExceptions thrown by SubjectCodeSource.implies - * @modules java.base/sun.security.provider - * @run main/othervm Comparator - * - * Note: if you want to see the java.security.debug output, - * you can not simply set the system property. - * you must run this test by hand and pass -Djava.security.debug=... - */ - -import java.io.*; -import java.security.*; -import java.util.PropertyPermission; -import javax.security.auth.Subject; -import javax.security.auth.x500.X500Principal; - -import sun.security.provider.PolicyFile; -import com.sun.security.auth.UnixPrincipal; -import com.sun.security.auth.NTUserPrincipal; - -public class Comparator { - - private static final PropertyPermission FOO = - new PropertyPermission("foo", "read"); - private static final PropertyPermission BAR = - new PropertyPermission("bar", "read"); - private static final PropertyPermission FOOBAR = - new PropertyPermission("foobar", "read"); - private static final PropertyPermission HELLO = - new PropertyPermission("hello", "read"); - private static final PropertyPermission WORLD = - new PropertyPermission("world", "read"); - - private static final CodeSource cs = - new CodeSource(null, (java.security.cert.Certificate[])null); - - private static final Principal[] p1 = new Principal[] { - new UnixPrincipal("1") }; - - private static final Principal[] p2 = new Principal[] { - new X500Principal("cn=2"), - new NTUserPrincipal("2") }; - - private static final Principal[] p3 = new Principal[] { - new UnixPrincipal("1"), - new X500Principal("cn=2"), - new NTUserPrincipal("2") }; - - private static final Principal[] p4 = new Principal[] { - new UnixPrincipal("1"), - new NTUserPrincipal("4") }; - - private static final Principal[] p5 = new Principal[] { - new UnixPrincipal("1"), - new X500Principal("cn=2"), - new NTUserPrincipal("2"), - new X500Principal("cn=x500") }; - - private static final Principal[] p6 = new Principal[] { - new UnixPrincipal("1"), - new NTUserPrincipal("4"), - new X500Principal("cn=x500") }; - - private static final Principal[] badP = new Principal[] { - new UnixPrincipal("bad") }; - - public static class PCompare1 implements Principal { - - private String name; - - public PCompare1(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean implies (Subject subject) { - if (subject.getPrincipals().contains(p1[0])) { - return true; - } - return false; - } - } - - public static class PCompare2 implements Principal { - private String name; - - public PCompare2(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean implies (Subject subject) { - if (subject.getPrincipals().contains(p2[0]) && - subject.getPrincipals().contains(p2[1])) { - return true; - } - return false; - } - } - - public static class PCompare3 implements Principal { - private String name; - - public PCompare3(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean implies (Subject subject) { - return false; - } - } - - public static void main(String[] args) throws Exception { - - int testnum = 1; - - // in case we run standalone - String policyDir = System.getProperty("test.src"); - if (policyDir == null) { - policyDir = "."; - } - - // do principal-only tests - System.setProperty("java.security.policy", - "=" + - policyDir + - File.separatorChar + - "Comparator.Principal.Policy"); - PolicyFile policy = new PolicyFile(); - testnum = doPrincipalTest(policy, testnum); - System.out.println("============ Principal Test Passed ============"); - - // do comparator-only tests - System.setProperty("java.security.policy", - "=" + - policyDir + - File.separatorChar + - "Comparator.Comparator.Policy"); - policy = new PolicyFile(); - testnum = doComparatorTest(policy, testnum); - System.out.println("============ Comparator Test Passed ============"); - - // combined principal/comparator tests - System.setProperty("java.security.policy", - "=" + - policyDir + - File.separatorChar + - "Comparator.Combined.Policy"); - policy = new PolicyFile(); - testnum = doCombinedTest(policy, testnum); - System.out.println("============ Combined Test Passed ============"); - } - - private static int doBadTest(PolicyFile policy, int testnum) { - - // this principal is not in policy - should not match any policy grants - ProtectionDomain pd = new ProtectionDomain(cs, null, null, badP); - if (policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // this principal is not in policy - should not match any policy grants - if (policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // this principal is not in policy - should not match any policy grants - if (policy.implies(pd, FOOBAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - return testnum; - } - - private static int doPrincipalTest(PolicyFile policy, int testnum) { - - // security check against one principal should pass - ProtectionDomain pd = new ProtectionDomain(cs, null, null, p1); - if (!policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match BAR grant entry in policy - pd = new ProtectionDomain(cs, null, null, p1); - if (policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against two principals should pass - pd = new ProtectionDomain(cs, null, null, p2); - if (!policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match FOOBAR grant entry in policy - pd = new ProtectionDomain(cs, null, null, p1); - if (policy.implies(pd, FOOBAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match FOOBAR grant entry in policy - pd = new ProtectionDomain(cs, null, null, p2); - if (policy.implies(pd, FOOBAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - testnum = doBadTest(policy, testnum); - - return testnum; - } - - private static int doComparatorTest(PolicyFile policy, int testnum) { - - // security check against one comparator should pass - ProtectionDomain pd = new ProtectionDomain(cs, null, null, p1); - if (!policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match BAR grant entry in policy - pd = new ProtectionDomain(cs, null, null, p1); - if (policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against two comparators should pass for FOO - pd = new ProtectionDomain(cs, null, null, p3); - if (!policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against two comparators should pass for BAR - pd = new ProtectionDomain(cs, null, null, p3); - if (!policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check should fail against FOOBAR - pd = new ProtectionDomain(cs, null, null, p3); - if (policy.implies(pd, FOOBAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - testnum = doBadTest(policy, testnum); - - return testnum; - } - - private static int doCombinedTest(PolicyFile policy, int testnum) { - - // security check against principal followed by comparator should pass - ProtectionDomain pd = new ProtectionDomain(cs, null, null, p3); - if (!policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match BAR grant entry in policy - pd = new ProtectionDomain(cs, null, null, p3); - if (policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against comparator followed by principal should pass - pd = new ProtectionDomain(cs, null, null, p4); - if (!policy.implies(pd, BAR)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match FOO grant entry in policy - pd = new ProtectionDomain(cs, null, null, p4); - if (policy.implies(pd, FOO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against principal-principal-comparator should pass - pd = new ProtectionDomain(cs, null, null, p5); - if (!policy.implies(pd, HELLO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match WORLD grant entry in policy - pd = new ProtectionDomain(cs, null, null, p5); - if (policy.implies(pd, WORLD)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // security check against principal-principal-comparator should pass - pd = new ProtectionDomain(cs, null, null, p6); - if (!policy.implies(pd, WORLD)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - // should not match HELLO grant entry in policy - pd = new ProtectionDomain(cs, null, null, p6); - if (policy.implies(pd, HELLO)) { - throw new SecurityException("test." + testnum + " failed"); - } - testnum++; - - testnum = doBadTest(policy, testnum); - - return testnum; - } -} diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirs.java b/test/jdk/sun/security/provider/PolicyParser/ExtDirs.java index 7cf0d2ca072..9a50d72ea0c 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirs.java +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,16 +26,15 @@ * @bug 4215035 * @summary standard extensions path is hard-coded in default * system policy file - * @run main/manual ExtDirs + * @run main ExtDirs */ /* - * Run this test manually with: - * java -Djava.security.manager \ - * -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \ - * -Djava.security.policy==./ExtDirs.policy \ - * -Djava.security.debug=parser \ - * ExtDirs + * @test + * @bug 4215035 + * @summary standard extensions path is hard-coded in default + * system policy file + * @run main/othervm/policy=ExtDirs.policy ExtDirs */ public class ExtDirs { diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirs.policy b/test/jdk/sun/security/provider/PolicyParser/ExtDirs.policy index ea172d89566..086ccbb8d83 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirs.policy +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirs.policy @@ -1,4 +1,4 @@ -grant codebase "${java.ext.dirs}" { +grant codebase "file:${test.classes}" { permission java.util.PropertyPermission "user.name", "read"; permission java.util.PropertyPermission "user.home", "read"; }; diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirs1.policy b/test/jdk/sun/security/provider/PolicyParser/ExtDirs1.policy index 7fe09732538..086ccbb8d83 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirs1.policy +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirs1.policy @@ -1,4 +1,4 @@ -grant codebase "file:${{java.ext.dirs}}/*" { +grant codebase "file:${test.classes}" { permission java.util.PropertyPermission "user.name", "read"; permission java.util.PropertyPermission "user.home", "read"; }; diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirs2.policy b/test/jdk/sun/security/provider/PolicyParser/ExtDirs2.policy index 10b4bc33566..9cc22d30d04 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirs2.policy +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirs2.policy @@ -1,4 +1,4 @@ -grant codebase "file:${{java.ext.dirs}}" { +grant codebase "file:${test.classes}/*" { permission java.util.PropertyPermission "user.name", "read"; permission java.util.PropertyPermission "user.home", "read"; }; diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirs3.policy b/test/jdk/sun/security/provider/PolicyParser/ExtDirs3.policy index 4b86743cbdf..9268094e707 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirs3.policy +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirs3.policy @@ -1,4 +1,4 @@ -grant codebase "${{java.ext.dirs}}" { +grant codebase "file:${test.classes}/-" { permission java.util.PropertyPermission "user.name", "read"; permission java.util.PropertyPermission "user.home", "read"; }; diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.java b/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.java index 1d0198e8295..da0dacff23d 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.java +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -26,30 +26,17 @@ * @bug 4993819 * @summary standard extensions path is hard-coded in default * system policy file - * @run main/manual ExtDirsChange + * @run main/othervm/policy=ExtDirsChange.policy ExtDirsChange */ -/* - * Run this test manually with: - * javac ExtDirChange - * rm ExtDirsA*.class ExtDirsB*.class - * java -Djava.security.manager \ - * -Dtest.src=. \ - * -Djava.security.policy=ExtDirsChange.policy \ - * -Djava.security.debug=parser \ - * -cp ExtDirsA/a.jar:ExtDirsB/b.jar:. \ - * ExtDirsChange - */ - -import java.io.File; import java.security.*; public class ExtDirsChange { public static void main(String args[]) throws Exception { - System.out.println("java.ext.dirs: " + - System.getProperty("java.ext.dirs")); + System.out.println("java.policy.dirs: " + + System.getProperty("java.policy.dirs")); - // Uses default security policy and java.ext.dirs + // Uses default security policy and java.policy.dirs try { ExtDirsA a = new ExtDirsA(); a.go(); @@ -58,14 +45,14 @@ public static void main(String args[]) throws Exception { System.out.println("Setup OK"); } - // Change java.ext.dirs and refresh policy + // Change java.policy.dirs and refresh policy AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - // Change java.ext.dirs - System.setProperty("java.ext.dirs", - "ExtDirsA" + File.pathSeparator + "ExtDirsB"); - System.out.println("java.ext.dirs: " + - System.getProperty("java.ext.dirs")); + // Change java.policy.dirs + System.setProperty("java.policy.dirs", + System.getProperty("test.classes")); + System.out.println("java.policy.dirs: " + + System.getProperty("java.policy.dirs")); return null; } }); @@ -79,7 +66,7 @@ public Object run() { System.out.println("Setup before refresh OK"); } - // Refresh policy using updated java.ext.dirs + // Refresh policy using updated java.policy.dirs AccessController.doPrivileged(new PrivilegedAction() { public Object run() { Policy.getPolicy().refresh(); @@ -99,13 +86,13 @@ public Object run() { } // Test with blank java.ext.dir - // Change java.ext.dirs and refresh policy + // Change java.policy.dirs and refresh policy AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - // Change java.ext.dirs - System.setProperty("java.ext.dirs", " "); - System.out.println("java.ext.dirs: " + - System.getProperty("java.ext.dirs")); + // Change java.policy.dirs + System.setProperty("java.policy.dirs", " "); + System.out.println("java.policy.dirs: " + + System.getProperty("java.policy.dirs")); Policy.getPolicy().refresh(); return null; } diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.policy b/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.policy index 85efce38f73..a158c66251b 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.policy +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirsChange.policy @@ -1,8 +1,16 @@ -grant codebase "file:${test.src}/*" { - permission java.security.AllPermission; +grant { + permission java.util.PropertyPermission "test.classes", "read"; + permission java.security.SecurityPermission "getPolicy"; + permission java.security.SecurityPermission "setPolicy"; }; -grant codebase "${java.ext.dirs}" { +grant codebase "file:${test.classes}/*" { + permission java.util.PropertyPermission "java.policy.dirs", "read, write"; + permission java.util.PropertyPermission "user.name", "write"; + permission java.util.PropertyPermission "user.home", "write"; +}; + +grant codebase "file:${java.policy.dirs}" { permission java.util.PropertyPermission "user.name", "read"; permission java.util.PropertyPermission "user.home", "read"; }; diff --git a/test/jdk/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java b/test/jdk/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java index e59a504bb00..30f570340e3 100644 --- a/test/jdk/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java +++ b/test/jdk/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -26,25 +26,34 @@ * @bug 4993819 * @summary standard extensions path is hard-coded in default * system policy file - * @run main/manual ExtDirsDefaultPolicy + * @run main ExtDirsDefaultPolicy */ /* - * Run this test manually with: - * java -Djava.security.manager \ - * -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \ - * -Djava.security.debug=parser \ - * ExtDirsDefaultPolicy + * @test + * @bug 4993819 + * @summary standard extensions path is hard-coded in default + * system policy file * - * To test other varients of the ${{java.ext.dirs}} protocol, remove - * the grant statement for java.ext.dirs in $JAVA_HOME/lib/security/java.policy - * and then run against the 3 different policy files. + * @run main/othervm/policy=ExtDirs1.policy ExtDirsDefaultPolicy + */ + +/* + * @test + * @bug 4993819 + * @summary standard extensions path is hard-coded in default + * system policy file + * + * @run main/othervm/policy=ExtDirs2.policy ExtDirsDefaultPolicy + */ + +/* + * @test + * @bug 4993819 + * @summary standard extensions path is hard-coded in default + * system policy file * - * java -Djava.security.manager \ - * -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \ - * -Djava.security.debug=parser \ - * -Djava.security.policy=ExtDirs{1,2,3}.policy \ - * ExtDirsDefaultPolicy + * @run main/othervm/policy=ExtDirs3.policy ExtDirsDefaultPolicy */ public class ExtDirsDefaultPolicy { diff --git a/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java b/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java index 9ff9a1b9d51..c01aaf8b00e 100644 --- a/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java +++ b/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,7 +25,7 @@ * @bug 8051408 8157308 8130181 * @modules java.base/sun.security.provider * @build java.base/sun.security.provider.S - * @run main SpecTest + * @run main/othervm -Djava.security.egd=file:/dev/urandom SpecTest * @summary check the AbstractDrbg API etc */ diff --git a/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java b/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java index 581dc54216b..01c3dfd06a1 100644 --- a/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java +++ b/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,7 +26,7 @@ * @bug 6998583 8141039 * @summary NativeSeedGenerator is making 8192 byte read requests from * entropy pool on each init. - * @run main/othervm -Djava.security.egd=file:/dev/random SeedGeneratorChoice + * @run main/othervm -Djava.security.egd=file:/dev/urandom SeedGeneratorChoice * @run main/othervm -Djava.security.egd=file:filename SeedGeneratorChoice */ diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumptionUpdateBoundValues.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumptionUpdateBoundValues.java index d537db8ae20..00ea4fc4ef1 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumptionUpdateBoundValues.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumptionUpdateBoundValues.java @@ -26,6 +26,7 @@ * @library /test/lib * @summary Test that a New Session Ticket will be generated when a * SSLSessionBindingListener is set (boundValues) + * @key intermittent * @run main/othervm ResumptionUpdateBoundValues */ diff --git a/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java b/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java index 24beb9f2f24..843a49bf33d 100644 --- a/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java +++ b/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java @@ -47,7 +47,7 @@ */ /* *
    mfDigest.equalsIgnoreCase(base64Digests[i])
    - * previously in JarSigner.java on on line 985 + * previously in JarSigner.java on line 985 * @see jdk.security.jarsigner.JarSigner#updateDigests */ public class DigestDontIgnoreCase { diff --git a/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java b/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java index e84edaf8e48..97436b76d31 100644 --- a/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java +++ b/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java @@ -217,7 +217,7 @@ public void startOfNextLengthWithBlankLine() throws Exception { *
  • which is then passed on as the third parameter to the constructor * of a new {@link ManifestDigester.Section#Section} by *
    new Section(0, pos.endOfSection + 1, pos.startOfNext, rawBytes)));
    - * in in ManifestDigester.java:128
  • + * in ManifestDigester.java:128 *
  • where it is assigned to * {@link ManifestDigester.Section#lengthWithBlankLine} by *
    this.lengthWithBlankLine = lengthWithBlankLine;
    diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java index 87fa6483009..b0e65f17441 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java @@ -1036,15 +1036,9 @@ private static OutputAnalyzer execTool(String toolPath, String... args) long start = System.currentTimeMillis(); try { String[] cmd; - if (Platform.isWindows()) { - cmd = new String[args.length + 3]; - System.arraycopy(args, 0, cmd, 3, args.length); - } else { - cmd = new String[args.length + 4]; - cmd[3] = "-J-Djava.security.egd=file:/dev/./urandom"; - System.arraycopy(args, 0, cmd, 4, args.length); - } + cmd = new String[args.length + 3]; + System.arraycopy(args, 0, cmd, 3, args.length); cmd[0] = toolPath; cmd[1] = "-J-Duser.language=en"; cmd[2] = "-J-Duser.country=US"; diff --git a/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java b/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java new file mode 100644 index 00000000000..63772eef335 --- /dev/null +++ b/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 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. + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import sun.security.x509.GeneralNameInterface; +import sun.security.x509.IPAddressName; + +import java.io.IOException; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @summary Verify IPAddressName.constrains + * @bug 8267617 + * @modules java.base/sun.security.x509 + * @run testng ConstrainsTest + */ +public class ConstrainsTest { + + IPAddressName ipv4Addr = new IPAddressName("127.0.0.1"); + IPAddressName ipv4Mask = new IPAddressName("127.0.0.0/255.0.0.0"); + IPAddressName ipv6Addr = new IPAddressName("::1"); + IPAddressName ipv6Mask = new IPAddressName("::/0"); + + public ConstrainsTest() throws IOException { + } + + @DataProvider(name = "names") + public Object[][] names() { + Object[][] data = { + {ipv4Addr, ipv4Addr, GeneralNameInterface.NAME_MATCH}, + {ipv4Addr, ipv4Mask, GeneralNameInterface.NAME_WIDENS}, + {ipv4Addr, ipv6Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Addr, ipv6Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Mask, ipv4Addr, GeneralNameInterface.NAME_NARROWS}, + {ipv4Mask, ipv4Mask, GeneralNameInterface.NAME_MATCH}, + {ipv4Mask, ipv6Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Mask, ipv6Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv4Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv4Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv6Addr, GeneralNameInterface.NAME_MATCH}, + {ipv6Addr, ipv6Mask, GeneralNameInterface.NAME_WIDENS}, + {ipv6Mask, ipv4Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Mask, ipv4Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Mask, ipv6Addr, GeneralNameInterface.NAME_NARROWS}, + {ipv6Mask, ipv6Mask, GeneralNameInterface.NAME_MATCH}, + }; + return data; + } + + @Test(dataProvider = "names") + public void testNameContains(IPAddressName addr1, IPAddressName addr2, int result) throws IOException { + assertEquals(addr1.constrains(addr2), result); + } + +} diff --git a/test/jdk/sun/tools/jhsdb/SAGetoptTest.java b/test/jdk/sun/tools/jhsdb/SAGetoptTest.java index 5ca48c629a3..37da2631a6a 100644 --- a/test/jdk/sun/tools/jhsdb/SAGetoptTest.java +++ b/test/jdk/sun/tools/jhsdb/SAGetoptTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -146,13 +146,13 @@ public static void main(String[] args) { // Bad options test String[] optionSet4 = {"-abd", "-c"}; - badOptionsTest(4, optionSet4, "Argument is expected for 'd'"); + badOptionsTest(4, optionSet4, "Successor argument without leading - is expected for 'd' but we got '-c'"); String[] optionSet5 = {"-exe", "bla", "--core"}; badOptionsTest(5, optionSet5, "Invalid option 'x'"); String[] optionSet6 = {"--exe", "--core", "bla_core"}; - badOptionsTest(6, optionSet6, "Argument is expected for 'exe'"); + badOptionsTest(6, optionSet6, "Successor argument without leading - is expected for 'exe' but we got '--core'"); String[] optionSet7 = {"--exe"}; badOptionsTest(7, optionSet7, "Argument is expected for 'exe'"); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 3fed83ddb36..72ebb64a142 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.spi.ToolProvider; import java.util.stream.Collectors; @@ -235,18 +236,49 @@ public List executeAndGetOutput() { return saveOutput().execute().getOutput(); } + private static class BadResultException extends RuntimeException { + BadResultException(Result v) { + value = v; + } + + Result getValue() { + return value; + } + + private final Result value; + } + /* * Repeates command "max" times and waits for "wait" seconds between each * execution until command returns expected error code. */ public Result executeAndRepeatUntilExitCode(int expectedCode, int max, int wait) { - Result result; + try { + return tryRunMultipleTimes(() -> { + Result result = executeWithoutExitCodeCheck(); + if (result.getExitCode() != expectedCode) { + throw new BadResultException(result); + } + return result; + }, max, wait).assertExitCodeIs(expectedCode); + } catch (BadResultException ex) { + return ex.getValue().assertExitCodeIs(expectedCode); + } + } + + /* + * Repeates a "task" "max" times and waits for "wait" seconds between each + * execution until the "task" returns without throwing an exception. + */ + public static T tryRunMultipleTimes(Supplier task, int max, int wait) { + RuntimeException lastException = null; int count = 0; do { - result = executeWithoutExitCodeCheck(); - if (result.getExitCode() == expectedCode) { - return result; + try { + return task.get(); + } catch (RuntimeException ex) { + lastException = ex; } try { @@ -258,7 +290,14 @@ public Result executeAndRepeatUntilExitCode(int expectedCode, int max, int wait) count++; } while (count < max); - return result.assertExitCodeIs(expectedCode); + throw lastException; + } + + public static void tryRunMultipleTimes(Runnable task, int max, int wait) { + tryRunMultipleTimes(() -> { + task.run(); + return null; + }, max, wait); } public List executeWithoutExitCodeCheckAndGetOutput() { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index c5bf16d1291..2de2e002a94 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -94,7 +94,9 @@ void verifyLauncherIcon(JPackageCommand cmd, String launcherName, Files.copy(getDefaultAppLauncher(expectedIcon == null && !expectedDefault), iconContainer); if (expectedIcon != null) { - setIcon(expectedIcon, iconContainer); + Executor.tryRunMultipleTimes(() -> { + setIcon(expectedIcon, iconContainer); + }, 3, 5); } Path extractedExpectedIcon = extractIconFromExecutable( @@ -169,9 +171,9 @@ private WinIconVerifier() { "unlockResource", long.class); unlockResource.setAccessible(true); - iconSwap = executableRebranderClass.getDeclaredMethod("iconSwap", - long.class, String.class); - iconSwap.setAccessible(true); + iconSwapWrapper = executableRebranderClass.getDeclaredMethod( + "iconSwapWrapper", long.class, String.class); + iconSwapWrapper.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { throw Functional.rethrowUnchecked(ex); @@ -180,8 +182,22 @@ private WinIconVerifier() { private Path extractIconFromExecutable(Path outputDir, Path executable, String label) { + // Run .NET code to extract icon from the given executable. + // ExtractAssociatedIcon() will succeed even if the target file + // is locked (by an antivirus). It will output a default icon + // in case of error. To prevent this "fail safe" behavior we try + // lock the target file with Open() call. If the attempt + // fails ExtractAssociatedIcon() is not called and the script exits + // with the exit code that will be trapped + // inside of Executor.executeAndRepeatUntilExitCode() method that + // will keep running the script until it succeeds or the number of + // allowed attempts is exceeded. + Path extractedIcon = outputDir.resolve(label + ".bmp"); String script = String.join(";", + String.format( + "try { [System.io.File]::Open('%s', 'Open', 'Read', 'None') } catch { exit 100 }", + executable.toAbsolutePath().normalize()), "[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')", String.format( "[System.Drawing.Icon]::ExtractAssociatedIcon('%s').ToBitmap().Save('%s', [System.Drawing.Imaging.ImageFormat]::Bmp)", @@ -189,7 +205,7 @@ private Path extractIconFromExecutable(Path outputDir, Path executable, extractedIcon.toAbsolutePath().normalize())); Executor.of("powershell", "-NoLogo", "-NoProfile", "-Command", - script).execute(); + script).executeAndRepeatUntilExitCode(0, 5, 10); return extractedIcon; } @@ -230,7 +246,7 @@ private void setIcon(Path iconPath, Path launcherPath) { "Failed to lock [%s] executable", launcherPath)); } - iconSwap.invoke(null, new Object[]{lock, + iconSwapWrapper.invoke(null, new Object[]{lock, iconPath.toAbsolutePath().normalize().toString()}); } finally { if (lock != 0) { @@ -250,7 +266,7 @@ private void setIcon(Path iconPath, Path launcherPath) { private final Class executableRebranderClass; private final Method lockResource; private final Method unlockResource; - private final Method iconSwap; + private final Method iconSwapWrapper; } private String launcherName; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 60492b2529f..9e4d2f86c00 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -180,10 +180,6 @@ public static boolean isOSX() { return (OS.contains("mac")); } - public static boolean isArmMac() { - return (isOSX() && "aarch64".equals(System.getProperty("os.arch"))); - } - public static boolean isLinux() { return ((OS.contains("nix") || OS.contains("nux"))); } diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index a493bc39127..666fafb7168 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -101,7 +101,7 @@ public void test() throws Exception { }) // On macOS aarch64 we always signing app image and signing will fail, since // test produces invalid app bundle. - .setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isArmMac() ? 1 : 0) + .setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isOSX() ? 1 : 0) .run(); } } diff --git a/test/jdk/tools/jpackage/windows/WinDirChooserTest.java b/test/jdk/tools/jpackage/windows/WinDirChooserTest.java index 2c5384f3561..355b89dba3e 100644 --- a/test/jdk/tools/jpackage/windows/WinDirChooserTest.java +++ b/test/jdk/tools/jpackage/windows/WinDirChooserTest.java @@ -42,7 +42,7 @@ * @build WinDirChooserTest * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinDirChooserTest */ diff --git a/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java b/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java index 450a98a40f4..63194d6b256 100644 --- a/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java +++ b/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java @@ -44,7 +44,7 @@ * @build WinInstallerIconTest * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinInstallerIconTest */ diff --git a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java index c6631bc008a..99c6eb490d5 100644 --- a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java +++ b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java @@ -45,7 +45,7 @@ * @build WinInstallerUiTest * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinInstallerUiTest */ public class WinInstallerUiTest { diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java index d5e84d6f867..deb6b1a8705 100644 --- a/test/jdk/tools/jpackage/windows/WinL10nTest.java +++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java @@ -48,7 +48,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinL10nTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinL10nTest */ diff --git a/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java b/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java index b8b748a6ca1..5950418f609 100644 --- a/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java +++ b/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java @@ -45,7 +45,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinMenuGroupTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinMenuGroupTest */ diff --git a/test/jdk/tools/jpackage/windows/WinMenuTest.java b/test/jdk/tools/jpackage/windows/WinMenuTest.java index e39a16465fe..a28d28e24ec 100644 --- a/test/jdk/tools/jpackage/windows/WinMenuTest.java +++ b/test/jdk/tools/jpackage/windows/WinMenuTest.java @@ -42,7 +42,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinMenuTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinMenuTest */ diff --git a/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java b/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java index 2020c27975b..5d97bb9357e 100644 --- a/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java +++ b/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java @@ -43,7 +43,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinPerUserInstallTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinPerUserInstallTest */ diff --git a/test/jdk/tools/jpackage/windows/WinScriptTest.java b/test/jdk/tools/jpackage/windows/WinScriptTest.java index 5e8c00bbddb..775102cd014 100644 --- a/test/jdk/tools/jpackage/windows/WinScriptTest.java +++ b/test/jdk/tools/jpackage/windows/WinScriptTest.java @@ -42,7 +42,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinScriptTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinScriptTest */ diff --git a/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java b/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java index 33d9a661ca3..6c27b6852eb 100644 --- a/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java +++ b/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java @@ -43,7 +43,7 @@ * @build WinShortcutPromptTest * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinShortcutPromptTest */ public class WinShortcutPromptTest { diff --git a/test/jdk/tools/jpackage/windows/WinShortcutTest.java b/test/jdk/tools/jpackage/windows/WinShortcutTest.java index f50f07a8905..3efa8b68817 100644 --- a/test/jdk/tools/jpackage/windows/WinShortcutTest.java +++ b/test/jdk/tools/jpackage/windows/WinShortcutTest.java @@ -43,7 +43,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinShortcutTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinShortcutTest */ diff --git a/test/jdk/tools/jpackage/windows/WinUrlTest.java b/test/jdk/tools/jpackage/windows/WinUrlTest.java index 8e1ffad8570..208d16d931a 100644 --- a/test/jdk/tools/jpackage/windows/WinUrlTest.java +++ b/test/jdk/tools/jpackage/windows/WinUrlTest.java @@ -46,7 +46,7 @@ * @build WinUrlTest * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinUrlTest */ public class WinUrlTest { diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 465e412b21b..04485c0d7ed 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc groups=TEST.groups # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Use new module options useNewOptions=true diff --git a/test/langtools/jdk/javadoc/doclet/5093723/T5093723.java b/test/langtools/jdk/javadoc/doclet/5093723/T5093723.java index cf5bb4a7cc6..f27b716ded1 100644 --- a/test/langtools/jdk/javadoc/doclet/5093723/T5093723.java +++ b/test/langtools/jdk/javadoc/doclet/5093723/T5093723.java @@ -36,7 +36,7 @@ public class T5093723 extends JavadocTester { public static void main(String... args) throws Exception { - T5093723 tester = new T5093723(); + var tester = new T5093723(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java b/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java index 9714154b9b3..8bd40055b77 100644 --- a/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java +++ b/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class AccessAsciiArt extends JavadocTester { public static void main(String... args) throws Exception { - AccessAsciiArt tester = new AccessAsciiArt(); + var tester = new AccessAsciiArt(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/AccessH1/AccessH1.java b/test/langtools/jdk/javadoc/doclet/AccessH1/AccessH1.java index b2e85525fdf..670cd703004 100644 --- a/test/langtools/jdk/javadoc/doclet/AccessH1/AccessH1.java +++ b/test/langtools/jdk/javadoc/doclet/AccessH1/AccessH1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class AccessH1 extends JavadocTester { public static void main(String... args) throws Exception { - AccessH1 tester = new AccessH1(); + var tester = new AccessH1(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java b/test/langtools/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java index 6577029c9cc..7e7a29e1515 100644 --- a/test/langtools/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java +++ b/test/langtools/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class AccessSkipNav extends JavadocTester { public static void main(String... args) throws Exception { - AccessSkipNav tester = new AccessSkipNav(); + var tester = new AccessSkipNav(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/AccessSummary/AccessSummary.java b/test/langtools/jdk/javadoc/doclet/AccessSummary/AccessSummary.java index dd4377fcc11..343a931b0ab 100644 --- a/test/langtools/jdk/javadoc/doclet/AccessSummary/AccessSummary.java +++ b/test/langtools/jdk/javadoc/doclet/AccessSummary/AccessSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -40,7 +40,7 @@ public class AccessSummary extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - AccessSummary tester = new AccessSummary(); + var tester = new AccessSummary(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/AuthorDD/AuthorDD.java b/test/langtools/jdk/javadoc/doclet/AuthorDD/AuthorDD.java index bbd89fee15a..75a52ce3ce1 100644 --- a/test/langtools/jdk/javadoc/doclet/AuthorDD/AuthorDD.java +++ b/test/langtools/jdk/javadoc/doclet/AuthorDD/AuthorDD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class AuthorDD extends JavadocTester { public static void main(String... args) throws Exception { - AuthorDD tester = new AuthorDD(); + var tester = new AuthorDD(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java b/test/langtools/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java index 52e547f7324..85b6d26aeeb 100644 --- a/test/langtools/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java +++ b/test/langtools/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -43,7 +43,7 @@ public class DocRootSlash extends JavadocTester { public static void main(String... args) throws Exception { - DocRootSlash tester = new DocRootSlash(); + var tester = new DocRootSlash(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java b/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java index 9685882bf51..4b9f55842c5 100644 --- a/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java +++ b/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java @@ -35,7 +35,7 @@ public class DocTest extends JavadocTester { public static void main(String... args) throws Exception { - DocTest tester = new DocTest(); + var tester = new DocTest(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java b/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java index 766765c6912..69b4dca6348 100644 --- a/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java +++ b/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class JavascriptWinTitle extends JavadocTester { public static void main(String... args) throws Exception { - JavascriptWinTitle tester = new JavascriptWinTitle(); + var tester = new JavascriptWinTitle(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java b/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java index f5d5a901a75..d4aa8a1ffeb 100644 --- a/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java +++ b/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -45,7 +45,7 @@ public class MetaTag extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - MetaTag tester = new MetaTag(); + var tester = new MetaTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/T6735320/T6735320.java b/test/langtools/jdk/javadoc/doclet/T6735320/T6735320.java index 7d945627596..9a5697f4099 100644 --- a/test/langtools/jdk/javadoc/doclet/T6735320/T6735320.java +++ b/test/langtools/jdk/javadoc/doclet/T6735320/T6735320.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,7 @@ public class T6735320 extends JavadocTester { public static void main(String... args) throws Exception { - T6735320 tester = new T6735320(); + var tester = new T6735320(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/ValidHtml/ValidHtml.java b/test/langtools/jdk/javadoc/doclet/ValidHtml/ValidHtml.java index 3a7443cbaea..303b77f5e55 100644 --- a/test/langtools/jdk/javadoc/doclet/ValidHtml/ValidHtml.java +++ b/test/langtools/jdk/javadoc/doclet/ValidHtml/ValidHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class ValidHtml extends JavadocTester { public static void main(String... args) throws Exception { - ValidHtml tester = new ValidHtml(); + var tester = new ValidHtml(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/VersionNumber/VersionNumber.java b/test/langtools/jdk/javadoc/doclet/VersionNumber/VersionNumber.java index 25702cf630b..55630abf245 100644 --- a/test/langtools/jdk/javadoc/doclet/VersionNumber/VersionNumber.java +++ b/test/langtools/jdk/javadoc/doclet/VersionNumber/VersionNumber.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -40,7 +40,7 @@ public class VersionNumber extends JavadocTester { public static void main(String... args) throws Exception { - VersionNumber tester = new VersionNumber(); + var tester = new VersionNumber(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/WindowTitles/WindowTitles.java b/test/langtools/jdk/javadoc/doclet/WindowTitles/WindowTitles.java index a40fae5932f..49706de79fe 100644 --- a/test/langtools/jdk/javadoc/doclet/WindowTitles/WindowTitles.java +++ b/test/langtools/jdk/javadoc/doclet/WindowTitles/WindowTitles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class WindowTitles extends JavadocTester { public static void main(String... args) throws Exception { - WindowTitles tester = new WindowTitles(); + var tester = new WindowTitles(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java b/test/langtools/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java index 92f0acaba44..4f6bdbc2537 100644 --- a/test/langtools/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java +++ b/test/langtools/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -35,7 +35,7 @@ public class TestConstantValuesDriver extends JavadocTester { public static void main(String... args) throws Exception { - TestConstantValuesDriver tester = new TestConstantValuesDriver(); + var tester = new TestConstantValuesDriver(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java b/test/langtools/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java index bf4e0189beb..0526d5bd1f0 100644 --- a/test/langtools/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java +++ b/test/langtools/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -35,7 +35,7 @@ public class TestDupThrowsTags extends JavadocTester { public static void main(String... args) throws Exception { - TestDupThrowsTags tester = new TestDupThrowsTags(); + var tester = new TestDupThrowsTags(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java b/test/langtools/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java index 72704b9ec93..1bbc2195d60 100644 --- a/test/langtools/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java +++ b/test/langtools/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestAbsLinkPath extends JavadocTester { public static void main(String... args) throws Exception { - TestAbsLinkPath tester = new TestAbsLinkPath(); + var tester = new TestAbsLinkPath(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java b/test/langtools/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java index d834bbae92f..baf5effba18 100644 --- a/test/langtools/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java +++ b/test/langtools/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -37,7 +37,7 @@ public class TestAbstractMethod extends JavadocTester { public static void main(String... args) throws Exception { - TestAbstractMethod tester = new TestAbstractMethod(); + var tester = new TestAbstractMethod(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java b/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java index 3c8a0a83ced..524048e5069 100644 --- a/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java +++ b/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -42,8 +42,8 @@ public class TestAnchorNames extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestAnchorNames tester = new TestAnchorNames(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestAnchorNames(); + tester.runTests(); } public TestAnchorNames() { diff --git a/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java b/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java index 0971d7c616d..14ba754abfa 100644 --- a/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java +++ b/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -37,7 +37,7 @@ public class TestAnnotationOptional extends JavadocTester { public static void main(String... args) throws Exception { - TestAnnotationOptional tester = new TestAnnotationOptional(); + var tester = new TestAnnotationOptional(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java index 81c4f7f1d16..9b2fc5e95bb 100644 --- a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -38,7 +38,7 @@ public class TestAnnotationTypes extends JavadocTester { public static void main(String... args) throws Exception { - TestAnnotationTypes tester = new TestAnnotationTypes(); + var tester = new TestAnnotationTypes(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAuthor/TestAuthor.java b/test/langtools/jdk/javadoc/doclet/testAuthor/TestAuthor.java index 58af165aabe..5229f8ccab5 100644 --- a/test/langtools/jdk/javadoc/doclet/testAuthor/TestAuthor.java +++ b/test/langtools/jdk/javadoc/doclet/testAuthor/TestAuthor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -42,7 +42,7 @@ public class TestAuthor extends JavadocTester { public static void main(String... args) throws Exception { - TestAuthor tester = new TestAuthor(); + var tester = new TestAuthor(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAutoHeaderId/TestAutoHeaderId.java b/test/langtools/jdk/javadoc/doclet/testAutoHeaderId/TestAutoHeaderId.java index aadf979a62f..eab52d836d0 100644 --- a/test/langtools/jdk/javadoc/doclet/testAutoHeaderId/TestAutoHeaderId.java +++ b/test/langtools/jdk/javadoc/doclet/testAutoHeaderId/TestAutoHeaderId.java @@ -40,7 +40,7 @@ public class TestAutoHeaderId extends JavadocTester { public static void main(String... args) throws Exception { - TestAutoHeaderId tester = new TestAutoHeaderId(); + var tester = new TestAutoHeaderId(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java b/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java index cd9d88cb423..c4d160d2d87 100644 --- a/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java +++ b/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -50,8 +50,8 @@ public class TestAutoLoadTaglets extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestAutoLoadTaglets tester = new TestAutoLoadTaglets(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestAutoLoadTaglets(); + tester.runTests(); } TestAutoLoadTaglets() { diff --git a/test/langtools/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java b/test/langtools/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java index e5ef8841239..0335af57b43 100644 --- a/test/langtools/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java +++ b/test/langtools/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestBackSlashInLink extends JavadocTester { public static void main(String... args) throws Exception { - TestBackSlashInLink tester = new TestBackSlashInLink(); + var tester = new TestBackSlashInLink(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testBadHtml/TestBadHtml.java b/test/langtools/jdk/javadoc/doclet/testBadHtml/TestBadHtml.java index 88aa55dffcf..0455882bf07 100644 --- a/test/langtools/jdk/javadoc/doclet/testBadHtml/TestBadHtml.java +++ b/test/langtools/jdk/javadoc/doclet/testBadHtml/TestBadHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestBadHtml extends JavadocTester { public static void main(String... args) throws Exception { - TestBadHtml tester = new TestBadHtml(); + var tester = new TestBadHtml(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java b/test/langtools/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java index e57062fd8ae..37844d28c1f 100644 --- a/test/langtools/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java +++ b/test/langtools/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -47,7 +47,7 @@ public class TestBadPackageFileInJar extends JavadocTester { final ToolBox tb = new ToolBox(); public static void main(String... args) throws Exception { - TestBadPackageFileInJar tester = new TestBadPackageFileInJar(); + var tester = new TestBadPackageFileInJar(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java b/test/langtools/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java index edc041c9406..92ae60b9142 100644 --- a/test/langtools/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java +++ b/test/langtools/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -42,7 +42,7 @@ public class TestBadSourceFile extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - TestBadSourceFile tester = new TestBadSourceFile(); + var tester = new TestBadSourceFile(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java b/test/langtools/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java index c26319d22dd..1711759ba3e 100644 --- a/test/langtools/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java +++ b/test/langtools/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestBaseClass extends JavadocTester { public static void main(String... args) throws Exception { - TestBaseClass tester = new TestBaseClass(); + var tester = new TestBaseClass(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testBimodalTaglets/TestBimodalTaglets.java b/test/langtools/jdk/javadoc/doclet/testBimodalTaglets/TestBimodalTaglets.java index 7e6cb4b3c76..c091d33845a 100644 --- a/test/langtools/jdk/javadoc/doclet/testBimodalTaglets/TestBimodalTaglets.java +++ b/test/langtools/jdk/javadoc/doclet/testBimodalTaglets/TestBimodalTaglets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -49,7 +49,7 @@ public class TestBimodalTaglets extends JavadocTester implements Taglet { public static void main(String... args) throws Exception { - new TestBimodalTaglets().runTests(m -> new Object[] { Path.of(m.getName()) }); + new TestBimodalTaglets().runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java b/test/langtools/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java index 4d33d550caf..72b1336dc59 100644 --- a/test/langtools/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java +++ b/test/langtools/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class TestBreakIterator extends JavadocTester { public static void main(String... args) throws Exception { - TestBreakIterator tester = new TestBreakIterator(); + var tester = new TestBreakIterator(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java b/test/langtools/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java index 1d68abffe32..5a0840f4f19 100644 --- a/test/langtools/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java +++ b/test/langtools/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -39,7 +39,7 @@ public class TestCRLineSeparator extends JavadocTester { public static void main(String... args) throws Exception { - TestCRLineSeparator tester = new TestCRLineSeparator(); + var tester = new TestCRLineSeparator(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCharset/TestCharset.java b/test/langtools/jdk/javadoc/doclet/testCharset/TestCharset.java index 2a5c05648f9..3900c2f27d8 100644 --- a/test/langtools/jdk/javadoc/doclet/testCharset/TestCharset.java +++ b/test/langtools/jdk/javadoc/doclet/testCharset/TestCharset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -37,7 +37,7 @@ public class TestCharset extends JavadocTester { public static void main(String... args) throws Exception { - TestCharset tester = new TestCharset(); + var tester = new TestCharset(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCharsetDocencodingOptions/TestCharsetDocencodingOptions.java b/test/langtools/jdk/javadoc/doclet/testCharsetDocencodingOptions/TestCharsetDocencodingOptions.java index 32c6c65dccc..d77993a083b 100644 --- a/test/langtools/jdk/javadoc/doclet/testCharsetDocencodingOptions/TestCharsetDocencodingOptions.java +++ b/test/langtools/jdk/javadoc/doclet/testCharsetDocencodingOptions/TestCharsetDocencodingOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestCharsetDocencodingOptions extends JavadocTester { public static void main(String... args) throws Exception { - TestCharsetDocencodingOptions tester = new TestCharsetDocencodingOptions(); + var tester = new TestCharsetDocencodingOptions(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java b/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java index c5145c148d7..93624a6dbeb 100644 --- a/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java +++ b/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class TestClassCrossReferences extends JavadocTester { static final String uri = "http://docs.oracle.com/javase/8/docs/api/"; public static void main(String... args) throws Exception { - TestClassCrossReferences tester = new TestClassCrossReferences(); + var tester = new TestClassCrossReferences(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testClassLinks/TestClassLinks.java b/test/langtools/jdk/javadoc/doclet/testClassLinks/TestClassLinks.java index 6a608b8c286..a2bffa15305 100644 --- a/test/langtools/jdk/javadoc/doclet/testClassLinks/TestClassLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testClassLinks/TestClassLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -37,7 +37,7 @@ public class TestClassLinks extends JavadocTester { public static void main(String... args) throws Exception { - TestClassLinks tester = new TestClassLinks(); + var tester = new TestClassLinks(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java b/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java index 520a87f406d..52a0e3ff55c 100644 --- a/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java +++ b/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -39,7 +39,7 @@ public class TestClassTree extends JavadocTester { public static void main(String... args) throws Exception { - TestClassTree tester = new TestClassTree(); + var tester = new TestClassTree(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java b/test/langtools/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java index fb466159d0d..285cd119ebd 100644 --- a/test/langtools/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java +++ b/test/langtools/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,7 @@ public class TestCmndLineClass extends JavadocTester { public static void main(String... args) throws Exception { - TestCmndLineClass tester = new TestCmndLineClass(); + var tester = new TestCmndLineClass(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java b/test/langtools/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java index b9c774b1454..d9ca6dd01df 100644 --- a/test/langtools/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java +++ b/test/langtools/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestCompletionFailure extends JavadocTester { public static void main(String... args) throws Exception { - TestCompletionFailure tester = new TestCompletionFailure(); + var tester = new TestCompletionFailure(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testConditionalPages/TestConditionalPages.java b/test/langtools/jdk/javadoc/doclet/testConditionalPages/TestConditionalPages.java index 413ef4b943e..6a02c1a8143 100644 --- a/test/langtools/jdk/javadoc/doclet/testConditionalPages/TestConditionalPages.java +++ b/test/langtools/jdk/javadoc/doclet/testConditionalPages/TestConditionalPages.java @@ -44,8 +44,8 @@ public class TestConditionalPages extends JavadocTester { public static void main(String... args) throws Exception { - TestConditionalPages tester = new TestConditionalPages(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestConditionalPages(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java b/test/langtools/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java index f3c743212c2..a796d6f0d19 100644 --- a/test/langtools/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java +++ b/test/langtools/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java @@ -39,7 +39,7 @@ public class TestConstantValuesPage extends JavadocTester { public static void main(String... args) throws Exception { - TestConstantValuesPage tester = new TestConstantValuesPage(); + var tester = new TestConstantValuesPage(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java b/test/langtools/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java index f24286d8752..01e2f25d69c 100644 --- a/test/langtools/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java +++ b/test/langtools/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestConstructorIndent extends JavadocTester { public static void main(String... args) throws Exception { - TestConstructorIndent tester = new TestConstructorIndent(); + var tester = new TestConstructorIndent(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testConstructors/TestConstructors.java b/test/langtools/jdk/javadoc/doclet/testConstructors/TestConstructors.java index 6e28ae543b9..86bb75cbacc 100644 --- a/test/langtools/jdk/javadoc/doclet/testConstructors/TestConstructors.java +++ b/test/langtools/jdk/javadoc/doclet/testConstructors/TestConstructors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestConstructors extends JavadocTester { public static void main(String... args) throws Exception { - TestConstructors tester = new TestConstructors(); + var tester = new TestConstructors(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java b/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java index ef1213f6ef8..5883bc928ae 100644 --- a/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java @@ -36,7 +36,7 @@ public class TestCopyFiles extends JavadocTester { public static void main(String... args) throws Exception { - TestCopyFiles tester = new TestCopyFiles(); + var tester = new TestCopyFiles(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java index 8d2d95d6a63..1b3a31b2ded 100644 --- a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -42,7 +42,7 @@ public class TestRegistrationErrors extends JavadocTester { public static void main(String... args) throws Exception { - TestRegistrationErrors tester = new TestRegistrationErrors(); + var tester = new TestRegistrationErrors(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java b/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java index 411e37efab9..970c7f8eea3 100644 --- a/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java +++ b/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java @@ -49,8 +49,8 @@ public class TestDateOption extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - TestDateOption tester = new TestDateOption(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestDateOption(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java index 09902319a05..1e742d4e412 100644 --- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java +++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java @@ -37,7 +37,7 @@ public class TestDeprecatedDocs extends JavadocTester { public static void main(String... args) throws Exception { - TestDeprecatedDocs tester = new TestDeprecatedDocs(); + var tester = new TestDeprecatedDocs(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDiagsLineCaret/TestDiagsLineCaret.java b/test/langtools/jdk/javadoc/doclet/testDiagsLineCaret/TestDiagsLineCaret.java index 415f7f706cf..f7ea316979c 100644 --- a/test/langtools/jdk/javadoc/doclet/testDiagsLineCaret/TestDiagsLineCaret.java +++ b/test/langtools/jdk/javadoc/doclet/testDiagsLineCaret/TestDiagsLineCaret.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,7 +40,7 @@ public class TestDiagsLineCaret extends JavadocTester { public static void main(String... args) throws Exception { - TestDiagsLineCaret tester = new TestDiagsLineCaret(); + var tester = new TestDiagsLineCaret(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java b/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java index 5021b50df17..b08b0558c8a 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java +++ b/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -43,7 +43,7 @@ public class TestDocEncoding extends JavadocTester { public static void main(String... args) throws Exception { - TestDocEncoding tester = new TestDocEncoding(); + var tester = new TestDocEncoding(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java b/test/langtools/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java index 427300d8931..aae9e523b0b 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java +++ b/test/langtools/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -42,7 +42,7 @@ public class TestDocErrorReporter extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - TestDocErrorReporter tester = new TestDocErrorReporter(); + var tester = new TestDocErrorReporter(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java b/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java index d2f9e98fa9c..479d896ef2d 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java +++ b/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -40,7 +40,7 @@ public class TestDocFileDir extends JavadocTester { public static void main(String... args) throws Exception { - TestDocFileDir tester = new TestDocFileDir(); + var tester = new TestDocFileDir(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java b/test/langtools/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java index c3f94515b36..4c5e27cb86b 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java +++ b/test/langtools/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -42,8 +42,8 @@ public class TestDocFiles extends JavadocTester { public static void main(String... args) throws Exception { - TestDocFiles tester = new TestDocFiles(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestDocFiles(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testDocLintOption/TestDocLintOption.java b/test/langtools/jdk/javadoc/doclet/testDocLintOption/TestDocLintOption.java index 55f696ec80b..d85c4ecdfd5 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocLintOption/TestDocLintOption.java +++ b/test/langtools/jdk/javadoc/doclet/testDocLintOption/TestDocLintOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -53,9 +53,9 @@ public class TestDocLintOption extends JavadocTester { public static void main(String... args) throws Exception { - TestDocLintOption tester = new TestDocLintOption(); + var tester = new TestDocLintOption(); tester.generateSrc(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testDocPaths/TestDocPaths.java b/test/langtools/jdk/javadoc/doclet/testDocPaths/TestDocPaths.java index 6178707bbd7..c4a09c9118b 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocPaths/TestDocPaths.java +++ b/test/langtools/jdk/javadoc/doclet/testDocPaths/TestDocPaths.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,7 +37,7 @@ public class TestDocPaths extends TestRunner { public static void main(String... args) throws Exception { - TestDocPaths tester = new TestDocPaths(); + var tester = new TestDocPaths(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java b/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java index 35d28ba3810..04d1e0f14db 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java +++ b/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,7 @@ public class TestDocRootInlineTag extends JavadocTester { public static void main(String... args) throws Exception { - TestDocRootInlineTag tester = new TestDocRootInlineTag(); + var tester = new TestDocRootInlineTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java b/test/langtools/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java index b8b69f05ff7..2a534495e56 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java +++ b/test/langtools/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -35,7 +35,7 @@ public class TestDocRootLink extends JavadocTester { public static void main(String... args) throws Exception { - TestDocRootLink tester = new TestDocRootLink(); + var tester = new TestDocRootLink(); // The test files intentionally contain examples of links that should // or should not be affected by the -Xdocrootparent option, and the diff --git a/test/langtools/jdk/javadoc/doclet/testDocTreeDiags/TestDocTreeDiags.java b/test/langtools/jdk/javadoc/doclet/testDocTreeDiags/TestDocTreeDiags.java index 375b45775ce..4172e2ef815 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocTreeDiags/TestDocTreeDiags.java +++ b/test/langtools/jdk/javadoc/doclet/testDocTreeDiags/TestDocTreeDiags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -65,8 +65,8 @@ public class TestDocTreeDiags extends JavadocTester { public static void main(String... args) throws Exception { - TestDocTreeDiags tester = new TestDocTreeDiags(); - tester.runTests(m -> new Object[] { Path.of(m.getName())} ); + var tester = new TestDocTreeDiags(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testDoclintDocletMessages/TestDocLintDocletMessages.java b/test/langtools/jdk/javadoc/doclet/testDoclintDocletMessages/TestDocLintDocletMessages.java index 049688e7fe8..e0ca7d5c1f5 100644 --- a/test/langtools/jdk/javadoc/doclet/testDoclintDocletMessages/TestDocLintDocletMessages.java +++ b/test/langtools/jdk/javadoc/doclet/testDoclintDocletMessages/TestDocLintDocletMessages.java @@ -47,7 +47,7 @@ public class TestDocLintDocletMessages extends JavadocTester { public static void main(String... args) throws Exception { - TestDocLintDocletMessages tester = new TestDocLintDocletMessages(); + var tester = new TestDocLintDocletMessages(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java b/test/langtools/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java index dde4a8fc6ad..cd8a425bd86 100644 --- a/test/langtools/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java +++ b/test/langtools/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestDupParamWarn extends JavadocTester { public static void main(String... args) throws Exception { - JavadocTester tester = new TestDupParamWarn(); + var tester = new TestDupParamWarn(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java b/test/langtools/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java index b55dfb35a89..c92a9f4162b 100644 --- a/test/langtools/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java +++ b/test/langtools/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -37,7 +37,7 @@ public class TestEmptyClass extends JavadocTester { public static void main(String... args) throws Exception { - TestEmptyClass tester = new TestEmptyClass(); + var tester = new TestEmptyClass(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testEmptyInheritDoc/TestEmptyInheritDoc.java b/test/langtools/jdk/javadoc/doclet/testEmptyInheritDoc/TestEmptyInheritDoc.java index 49a29c29c4d..c969fcb834d 100644 --- a/test/langtools/jdk/javadoc/doclet/testEmptyInheritDoc/TestEmptyInheritDoc.java +++ b/test/langtools/jdk/javadoc/doclet/testEmptyInheritDoc/TestEmptyInheritDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -42,7 +42,7 @@ public class TestEmptyInheritDoc extends JavadocTester { public static void main(String... args) throws Exception { - TestEmptyInheritDoc tester = new TestEmptyInheritDoc(); + var tester = new TestEmptyInheritDoc(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java b/test/langtools/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java index b1f60eae32b..e744661cc8b 100644 --- a/test/langtools/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java +++ b/test/langtools/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -36,7 +36,7 @@ public class TestEnclosingClass extends JavadocTester { public static void main(String... args) throws Exception { - TestEnclosingClass tester = new TestEnclosingClass(); + var tester = new TestEnclosingClass(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testEncoding/TestEncoding.java b/test/langtools/jdk/javadoc/doclet/testEncoding/TestEncoding.java index cbd8d26bd2d..ec028c7d8fd 100644 --- a/test/langtools/jdk/javadoc/doclet/testEncoding/TestEncoding.java +++ b/test/langtools/jdk/javadoc/doclet/testEncoding/TestEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestEncoding extends JavadocTester { public static void main(String... args) throws Exception { - TestEncoding tester = new TestEncoding(); + var tester = new TestEncoding(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testEnumConstructor/TestEnumConstructor.java b/test/langtools/jdk/javadoc/doclet/testEnumConstructor/TestEnumConstructor.java index e6dadfcecdd..225893cb417 100644 --- a/test/langtools/jdk/javadoc/doclet/testEnumConstructor/TestEnumConstructor.java +++ b/test/langtools/jdk/javadoc/doclet/testEnumConstructor/TestEnumConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -44,8 +44,8 @@ public class TestEnumConstructor extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestEnumConstructor tester = new TestEnumConstructor(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestEnumConstructor(); + tester.runTests(); } TestEnumConstructor() { diff --git a/test/langtools/jdk/javadoc/doclet/testExceptionInheritance/TestExceptionInheritance.java b/test/langtools/jdk/javadoc/doclet/testExceptionInheritance/TestExceptionInheritance.java index e61b2cfc7b0..ad5e910a94e 100644 --- a/test/langtools/jdk/javadoc/doclet/testExceptionInheritance/TestExceptionInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testExceptionInheritance/TestExceptionInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,8 +40,8 @@ public class TestExceptionInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestExceptionInheritance tester = new TestExceptionInheritance(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestExceptionInheritance(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testExternalOverriddenMethod/TestExternalOverriddenMethod.java b/test/langtools/jdk/javadoc/doclet/testExternalOverriddenMethod/TestExternalOverriddenMethod.java index ec770e26dff..d98387082a5 100644 --- a/test/langtools/jdk/javadoc/doclet/testExternalOverriddenMethod/TestExternalOverriddenMethod.java +++ b/test/langtools/jdk/javadoc/doclet/testExternalOverriddenMethod/TestExternalOverriddenMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,7 +39,7 @@ public class TestExternalOverriddenMethod extends JavadocTester { static final String uri = "http://java.sun.com/j2se/1.4.1/docs/api"; public static void main(String... args) throws Exception { - TestExternalOverriddenMethod tester = new TestExternalOverriddenMethod(); + var tester = new TestExternalOverriddenMethod(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java b/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java index 4d7ad533152..4cd8284791b 100644 --- a/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java +++ b/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,7 +36,7 @@ public class TestGeneratedBy extends JavadocTester { public static void main(String... args) throws Exception { - TestGeneratedBy tester = new TestGeneratedBy(); + var tester = new TestGeneratedBy(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testGeneratedClasses/TestGeneratedClasses.java b/test/langtools/jdk/javadoc/doclet/testGeneratedClasses/TestGeneratedClasses.java index 9ffbc8baa8b..c412ce49f98 100644 --- a/test/langtools/jdk/javadoc/doclet/testGeneratedClasses/TestGeneratedClasses.java +++ b/test/langtools/jdk/javadoc/doclet/testGeneratedClasses/TestGeneratedClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -39,8 +39,8 @@ public class TestGeneratedClasses extends JavadocTester { public static void main(String... args) throws Exception { - TestGeneratedClasses tester = new TestGeneratedClasses(); - tester.runTests(m -> new Object[]{Path.of(m.getName())}); + var tester = new TestGeneratedClasses(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java index a6d7e381869..a9a4be1b262 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -45,8 +45,8 @@ public class TestGenericMethodLinkTaglet extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestGenericMethodLinkTaglet tester = new TestGenericMethodLinkTaglet(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestGenericMethodLinkTaglet(); + tester.runTests(); } TestGenericMethodLinkTaglet() { diff --git a/test/langtools/jdk/javadoc/doclet/testGrandParentTypes/TestGrandParentTypes.java b/test/langtools/jdk/javadoc/doclet/testGrandParentTypes/TestGrandParentTypes.java index 3d20cf8a95b..779f9fbbb81 100644 --- a/test/langtools/jdk/javadoc/doclet/testGrandParentTypes/TestGrandParentTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testGrandParentTypes/TestGrandParentTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -37,7 +37,7 @@ public class TestGrandParentTypes extends JavadocTester { public static void main(String... args) throws Exception { - TestGrandParentTypes tester = new TestGrandParentTypes(); + var tester = new TestGrandParentTypes(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java b/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java index 743fc72e90d..84e4d140d95 100644 --- a/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java +++ b/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -42,8 +42,8 @@ public class TestGroupName extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestGroupName tester = new TestGroupName(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestGroupName(); + tester.runTests(); } public TestGroupName() { diff --git a/test/langtools/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java b/test/langtools/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java index ef8baf55972..3a946f328d6 100644 --- a/test/langtools/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java +++ b/test/langtools/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestGroupOption extends JavadocTester { public static void main(String... args) throws Exception { - TestGroupOption tester = new TestGroupOption(); + var tester = new TestGroupOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHeadTag/TestHeadTag.java b/test/langtools/jdk/javadoc/doclet/testHeadTag/TestHeadTag.java index e6a657d7ef4..547592277c1 100644 --- a/test/langtools/jdk/javadoc/doclet/testHeadTag/TestHeadTag.java +++ b/test/langtools/jdk/javadoc/doclet/testHeadTag/TestHeadTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -47,8 +47,8 @@ public class TestHeadTag extends JavadocTester { final String version = System.getProperty("java.specification.version"); public static void main(String... args) throws Exception { - TestHeadTag tester = new TestHeadTag(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestHeadTag(); + tester.runTests(); } TestHeadTag() { diff --git a/test/langtools/jdk/javadoc/doclet/testHeadings/TestHeadings.java b/test/langtools/jdk/javadoc/doclet/testHeadings/TestHeadings.java index dfa22f8edb0..1e9867fcb65 100644 --- a/test/langtools/jdk/javadoc/doclet/testHeadings/TestHeadings.java +++ b/test/langtools/jdk/javadoc/doclet/testHeadings/TestHeadings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestHeadings extends JavadocTester { public static void main(String... args) throws Exception { - TestHeadings tester = new TestHeadings(); + var tester = new TestHeadings(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java b/test/langtools/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java index df544cd8110..462bc872161 100644 --- a/test/langtools/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java +++ b/test/langtools/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -38,7 +38,7 @@ public class TestHelpFile extends JavadocTester { public static final int ZERO = 0; public static void main(String... args) throws Exception { - TestHelpFile tester = new TestHelpFile(); + var tester = new TestHelpFile(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java b/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java index 80765fac5d0..b2f4bba3bf1 100644 --- a/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java +++ b/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,7 +39,7 @@ public class TestHelpOption extends JavadocTester { public static void main(String... args) throws Exception { - TestHelpOption tester = new TestHelpOption(); + var tester = new TestHelpOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHelpPage/TestHelpPage.java b/test/langtools/jdk/javadoc/doclet/testHelpPage/TestHelpPage.java index a3ee65ac70d..bdd4c914eec 100644 --- a/test/langtools/jdk/javadoc/doclet/testHelpPage/TestHelpPage.java +++ b/test/langtools/jdk/javadoc/doclet/testHelpPage/TestHelpPage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -40,7 +40,7 @@ public class TestHelpPage extends JavadocTester { public static void main(String... args) throws Exception { - TestHelpPage tester = new TestHelpPage(); + var tester = new TestHelpPage(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java b/test/langtools/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java index e9a35475df5..b094ab537af 100644 --- a/test/langtools/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java +++ b/test/langtools/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -45,7 +45,7 @@ public class TestHiddenMembers extends JavadocTester { }; public static void main(String... args) throws Exception { - TestHiddenMembers tester = new TestHiddenMembers(); + var tester = new TestHiddenMembers(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java b/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java index 75b38453614..1cad5678258 100644 --- a/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java +++ b/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -36,7 +36,7 @@ public class TestHiddenTag extends JavadocTester { public static void main(String... args) throws Exception { - TestHiddenTag tester = new TestHiddenTag(); + var tester = new TestHiddenTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java index 8ab798a88a1..938bae79f6c 100644 --- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java +++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -36,7 +36,7 @@ public class TestHref extends JavadocTester { public static void main(String... args) throws Exception { - TestHref tester = new TestHref(); + var tester = new TestHref(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java index 5af53e19048..830920159f3 100644 --- a/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java +++ b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestHrefInDocComment extends JavadocTester { public static void main(String... args) throws Exception { - TestHrefInDocComment tester = new TestHrefInDocComment(); + var tester = new TestHrefInDocComment(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtml4Removal/TestHtml4Removal.java b/test/langtools/jdk/javadoc/doclet/testHtml4Removal/TestHtml4Removal.java index 09329a769bc..8049cb75df8 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtml4Removal/TestHtml4Removal.java +++ b/test/langtools/jdk/javadoc/doclet/testHtml4Removal/TestHtml4Removal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -44,7 +44,7 @@ public static void main(String... args) throws Exception { Files.write(testFile, List.of("/** Comment. */", "public class C { }")); - TestHtml4Removal tester = new TestHtml4Removal(); + var tester = new TestHtml4Removal(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java b/test/langtools/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java index 38b8fb9a270..ed2966d1fb7 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestHtmlComments extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlComments tester = new TestHtmlComments(); + var tester = new TestHtmlComments(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java b/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java index 4f0c0ee04c2..38aa793fcee 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java @@ -41,7 +41,7 @@ public class TestHtmlDefinitionListTag extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlDefinitionListTag tester = new TestHtmlDefinitionListTag(); + var tester = new TestHtmlDefinitionListTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java b/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java index 8d04bb61534..7472a2c397e 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java @@ -46,7 +46,7 @@ public class TestHtmlDocument extends JavadocTester { // Entry point public static void main(String... args) throws Exception { - TestHtmlDocument tester = new TestHtmlDocument(); + var tester = new TestHtmlDocument(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java b/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java index 1577d6d563f..8a265cef4f1 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -51,8 +51,8 @@ public class TestHtmlLandmarkRegions extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestHtmlLandmarkRegions tester = new TestHtmlLandmarkRegions(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestHtmlLandmarkRegions(); + tester.runTests(); } TestHtmlLandmarkRegions() { diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java b/test/langtools/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java index 74f9a9a210e..4d18c9c351a 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -36,7 +36,7 @@ public class TestHtmlStrongTag extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlStrongTag tester = new TestHtmlStrongTag(); + var tester = new TestHtmlStrongTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java b/test/langtools/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java index 32c23d6bf42..930445113f0 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestHtmlTableStyles extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlTableStyles tester = new TestHtmlTableStyles(); + var tester = new TestHtmlTableStyles(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java b/test/langtools/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java index 4afd8d91cec..61cd6f77566 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java @@ -42,7 +42,7 @@ public class TestHtmlTableTags extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlTableTags tester = new TestHtmlTableTags(); + var tester = new TestHtmlTableTags(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java b/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java index 0aa51351f8d..083bf94ed4d 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -38,7 +38,7 @@ public class TestHtmlTag extends JavadocTester { private static final String defaultLanguage = Locale.getDefault().getLanguage(); public static void main(String... args) throws Exception { - TestHtmlTag tester = new TestHtmlTag(); + var tester = new TestHtmlTag(); tester.runTests(); } @Test diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java index 68393890fa3..d850b3a8baf 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java @@ -37,7 +37,7 @@ public class TestHtmlVersion extends JavadocTester { public static void main(String... args) throws Exception { - TestHtmlVersion tester = new TestHtmlVersion(); + var tester = new TestHtmlVersion(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java index aea2233e4d2..9127cdf86bb 100644 --- a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java +++ b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -49,7 +49,7 @@ public class TestIOException extends JavadocTester { public static void main(String... args) throws Exception { - TestIOException tester = new TestIOException(); + var tester = new TestIOException(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIncluded/TestIncluded.java b/test/langtools/jdk/javadoc/doclet/testIncluded/TestIncluded.java index a65ddc737f3..2071cee29b4 100644 --- a/test/langtools/jdk/javadoc/doclet/testIncluded/TestIncluded.java +++ b/test/langtools/jdk/javadoc/doclet/testIncluded/TestIncluded.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -36,7 +36,7 @@ public class TestIncluded extends JavadocTester { public static void main(String... args) throws Exception { - TestIncluded tester = new TestIncluded(); + var tester = new TestIncluded(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIndentation/TestIndentation.java b/test/langtools/jdk/javadoc/doclet/testIndentation/TestIndentation.java index 86fac93d7fe..b912e69efaf 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndentation/TestIndentation.java +++ b/test/langtools/jdk/javadoc/doclet/testIndentation/TestIndentation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestIndentation extends JavadocTester { public static void main(String... args) throws Exception { - TestIndentation tester = new TestIndentation(); + var tester = new TestIndentation(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIndex/TestIndex.java b/test/langtools/jdk/javadoc/doclet/testIndex/TestIndex.java index b068b700845..5bc94fa63b4 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndex/TestIndex.java +++ b/test/langtools/jdk/javadoc/doclet/testIndex/TestIndex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -38,7 +38,7 @@ public class TestIndex extends JavadocTester { public static void main(String... args) throws Exception { - TestIndex tester = new TestIndex(); + var tester = new TestIndex(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIndexFiles/TestIndexFiles.java b/test/langtools/jdk/javadoc/doclet/testIndexFiles/TestIndexFiles.java index 904061cb8aa..7b3315f68e1 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndexFiles/TestIndexFiles.java +++ b/test/langtools/jdk/javadoc/doclet/testIndexFiles/TestIndexFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestIndexFiles extends JavadocTester { public static void main(String... args) throws Exception { - TestIndexFiles tester = new TestIndexFiles(); + var tester = new TestIndexFiles(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIndexInDocFiles/TestIndexInDocFiles.java b/test/langtools/jdk/javadoc/doclet/testIndexInDocFiles/TestIndexInDocFiles.java index 166df110ee6..1f724cf83fe 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndexInDocFiles/TestIndexInDocFiles.java +++ b/test/langtools/jdk/javadoc/doclet/testIndexInDocFiles/TestIndexInDocFiles.java @@ -45,8 +45,8 @@ public class TestIndexInDocFiles extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestIndexInDocFiles tester = new TestIndexInDocFiles(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestIndexInDocFiles(); + tester.runTests(); } TestIndexInDocFiles() { diff --git a/test/langtools/jdk/javadoc/doclet/testIndexInPackageFiles/TestIndexInPackageFiles.java b/test/langtools/jdk/javadoc/doclet/testIndexInPackageFiles/TestIndexInPackageFiles.java index d400c310203..9e72fca9b5b 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndexInPackageFiles/TestIndexInPackageFiles.java +++ b/test/langtools/jdk/javadoc/doclet/testIndexInPackageFiles/TestIndexInPackageFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -40,7 +40,7 @@ public class TestIndexInPackageFiles extends JavadocTester { public static void main(String... args) throws Exception { - TestIndexInPackageFiles tester = new TestIndexInPackageFiles (); + var tester = new TestIndexInPackageFiles (); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testIndexTaglet/TestIndexTaglet.java b/test/langtools/jdk/javadoc/doclet/testIndexTaglet/TestIndexTaglet.java index e14b42f4527..1707eb52532 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndexTaglet/TestIndexTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testIndexTaglet/TestIndexTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -46,8 +46,8 @@ public class TestIndexTaglet extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestIndexTaglet tester = new TestIndexTaglet(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestIndexTaglet(); + tester.runTests(); } TestIndexTaglet() { diff --git a/test/langtools/jdk/javadoc/doclet/testIndexWithModules/TestIndexWithModules.java b/test/langtools/jdk/javadoc/doclet/testIndexWithModules/TestIndexWithModules.java index 4c22c7ccf19..ce1e46bbffd 100644 --- a/test/langtools/jdk/javadoc/doclet/testIndexWithModules/TestIndexWithModules.java +++ b/test/langtools/jdk/javadoc/doclet/testIndexWithModules/TestIndexWithModules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -50,8 +50,8 @@ public class TestIndexWithModules extends JavadocTester { private final Path src; public static void main(String... args) throws Exception { - TestIndexWithModules tester = new TestIndexWithModules(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestIndexWithModules(); + tester.runTests(); } TestIndexWithModules() throws Exception{ diff --git a/test/langtools/jdk/javadoc/doclet/testInheritDocWithinInappropriateTag/TestInheritDocWithinInappropriateTag.java b/test/langtools/jdk/javadoc/doclet/testInheritDocWithinInappropriateTag/TestInheritDocWithinInappropriateTag.java index c75749a5503..49e1c406a16 100644 --- a/test/langtools/jdk/javadoc/doclet/testInheritDocWithinInappropriateTag/TestInheritDocWithinInappropriateTag.java +++ b/test/langtools/jdk/javadoc/doclet/testInheritDocWithinInappropriateTag/TestInheritDocWithinInappropriateTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8284299 8287379 + * @bug 8284299 8287379 8298525 * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox javadoc.tester.* @@ -39,7 +39,7 @@ public class TestInheritDocWithinInappropriateTag extends JavadocTester { public static void main(String... args) throws Exception { new TestInheritDocWithinInappropriateTag() - .runTests(m -> new Object[]{Path.of(m.getName())}); + .runTests(); } private final ToolBox tb = new ToolBox(); @@ -65,6 +65,9 @@ public class B extends A { * {@linkplain Object#hashCode() {@inheritDoc}} * * {@index term {@inheritDoc}} + * + * @see A {@inheritDoc} + * @spec http://example.com {@inheritDoc} */ @Override public void x() { } @@ -95,6 +98,16 @@ public void x() { } warning: @inheritDoc cannot be used within this tag * {@index term {@inheritDoc}} ^ + """, + """ + warning: @inheritDoc cannot be used within this tag + * @see A {@inheritDoc} + ^ + """, + """ + warning: @inheritDoc cannot be used within this tag + * @spec http://example.com {@inheritDoc} + ^ """); } diff --git a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java index 0806278b43d..f188ffaef98 100644 --- a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java +++ b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -39,8 +39,8 @@ public class TestInherited extends JavadocTester { public static void main(String... args) throws Exception { - TestInherited tester = new TestInherited(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestInherited(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java b/test/langtools/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java index f1170dff030..2de58cfdbdd 100644 --- a/test/langtools/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java +++ b/test/langtools/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestInlineLinkLabel extends JavadocTester { public static void main(String... args) throws Exception { - TestInlineLinkLabel tester = new TestInlineLinkLabel(); + var tester = new TestInlineLinkLabel(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java index 83530f32368..29039cf9fa6 100644 --- a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java +++ b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java @@ -54,7 +54,7 @@ public class TestInterface extends JavadocTester { public static void main(String... args) throws Exception { - TestInterface tester = new TestInterface(); + var tester = new TestInterface(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java index 14651bf1c71..c513bc2a8a9 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -41,7 +41,7 @@ public class TestFxProperties extends JavadocTester { public static void main(String... args) throws Exception { - TestFxProperties tester = new TestFxProperties(); + var tester = new TestFxProperties(); if (!tester.sanity()) { return; } diff --git a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java index e493a35a28e..da10634d250 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -42,7 +42,7 @@ public class TestJavaFX extends JavadocTester { public static void main(String... args) throws Exception { - TestJavaFX tester = new TestJavaFX(); + var tester = new TestJavaFX(); tester.setAutomaticCheckAccessibility(false); tester.setAutomaticCheckLinks(false); tester.runTests(); diff --git a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXCombo.java b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXCombo.java index f0f643b4387..e8f6782014d 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXCombo.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -49,8 +49,8 @@ */ public class TestJavaFXCombo extends JavadocTester { public static void main(String... args) throws Exception { - TestJavaFXCombo tester = new TestJavaFXCombo(args); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestJavaFXCombo(args); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXMissingPropComments.java b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXMissingPropComments.java index 46b819c6da9..15ef52b3b9e 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXMissingPropComments.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFXMissingPropComments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -39,8 +39,8 @@ public class TestJavaFXMissingPropComments extends JavadocTester { public static void main(String... args) throws Exception { - TestJavaFXMissingPropComments tester = new TestJavaFXMissingPropComments(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestJavaFXMissingPropComments(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFxMode.java b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFxMode.java index ae3d8de1491..2b10fe9e229 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFxMode.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFxMode.java @@ -43,9 +43,9 @@ public class TestJavaFxMode extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestJavaFxMode tester = new TestJavaFxMode(); + var tester = new TestJavaFxMode(); if (tester.sanity()) { - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + tester.runTests(); } } diff --git a/test/langtools/jdk/javadoc/doclet/testJavaPackage/TestJavaPackage.java b/test/langtools/jdk/javadoc/doclet/testJavaPackage/TestJavaPackage.java index 92cf4a91417..130912ddfe3 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavaPackage/TestJavaPackage.java +++ b/test/langtools/jdk/javadoc/doclet/testJavaPackage/TestJavaPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -44,7 +44,7 @@ public class TestJavaPackage extends JavadocTester { public static void main(String... args) throws Exception { - TestJavaPackage tester = new TestJavaPackage(); + var tester = new TestJavaPackage(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java b/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java index 6cc05346a66..1f927650cde 100644 --- a/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java +++ b/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -36,7 +36,7 @@ public class TestJavascript extends JavadocTester { public static void main(String... args) throws Exception { - TestJavascript tester = new TestJavascript(); + var tester = new TestJavascript(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java b/test/langtools/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java index 52b57410ae4..34e8a0c6f6d 100644 --- a/test/langtools/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java +++ b/test/langtools/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -43,7 +43,7 @@ public class LeadingSpaces extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - LeadingSpaces tester = new LeadingSpaces(); + var tester = new LeadingSpaces(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java b/test/langtools/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java index 192158f89d2..589502df760 100644 --- a/test/langtools/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestLegacyTaglet extends JavadocTester { public static void main(String... args) throws Exception { - TestLegacyTaglet tester = new TestLegacyTaglet(); + var tester = new TestLegacyTaglet(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLegalNotices/TestLegalNotices.java b/test/langtools/jdk/javadoc/doclet/testLegalNotices/TestLegalNotices.java index e844d14d72d..cf77d793512 100644 --- a/test/langtools/jdk/javadoc/doclet/testLegalNotices/TestLegalNotices.java +++ b/test/langtools/jdk/javadoc/doclet/testLegalNotices/TestLegalNotices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -47,8 +47,8 @@ public class TestLegalNotices extends JavadocTester { public static void main(String... args) throws Exception { - TestLegalNotices tester = new TestLegalNotices(); - tester.runTests(m -> new Object[]{Path.of(m.getName())}); + var tester = new TestLegalNotices(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java index 5d8589a6f5a..ac6464f9104 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -36,7 +36,7 @@ public class TestBadLinkOption extends JavadocTester { public static void main(String... args) throws Exception { - TestBadLinkOption tester = new TestBadLinkOption(); + var tester = new TestBadLinkOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java index f4f85c50d47..66cfa3ff27d 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -43,7 +43,7 @@ public class TestLinkOption extends JavadocTester { * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { - TestLinkOption tester = new TestLinkOption(); + var tester = new TestLinkOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java index d293e525326..fb31822d0e9 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -48,8 +48,8 @@ public class TestLinkOptionWithAutomaticModule extends JavadocTester { public static void main(String... args) throws Exception { - TestLinkOptionWithAutomaticModule tester = new TestLinkOptionWithAutomaticModule(); - tester.runTests(m -> new Object[]{ Path.of(m.getName()) }); + var tester = new TestLinkOptionWithAutomaticModule(); + tester.runTests(); } final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java index 4f7602251d8..113cde3c60d 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -51,8 +51,8 @@ public class TestLinkOptionWithModule extends JavadocTester { private final Path moduleSrc, packageSrc; public static void main(String... args) throws Exception { - TestLinkOptionWithModule tester = new TestLinkOptionWithModule(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestLinkOptionWithModule(); + tester.runTests(); } TestLinkOptionWithModule() throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java index 22234fe4d55..6ddfb6fde7c 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestNewLineInLink extends JavadocTester { public static void main(String... args) throws Exception { - TestNewLineInLink tester = new TestNewLineInLink(); + var tester = new TestNewLineInLink(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestOptionOrder.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestOptionOrder.java index 28ffa7c86aa..64522223b4a 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestOptionOrder.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestOptionOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -52,8 +52,8 @@ public class TestOptionOrder extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestOptionOrder tester = new TestOptionOrder(); - tester.runTests(m -> new Object[] { Path.of(m.getName())} ); + var tester = new TestOptionOrder(); + tester.runTests(); } TestOptionOrder() throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java index ce7192cced9..ec7e63115a6 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -26,11 +26,14 @@ * @bug 8190312 * @summary test redirected URLs for -link * @library /tools/lib ../../lib + * @library /test/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.javadoc/jdk.javadoc.internal.api * jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox toolbox.JavacTask javadoc.tester.* + * @build jtreg.SkippedException + * @build jdk.test.lib.Platform * @run main TestRedirectLinks */ @@ -66,13 +69,19 @@ import toolbox.JavacTask; import toolbox.ToolBox; +import jdk.test.lib.Platform; +import jtreg.SkippedException; + public class TestRedirectLinks extends JavadocTester { /** * The entry point of the test. * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { - TestRedirectLinks tester = new TestRedirectLinks(); + if (Platform.isSlowDebugBuild()) { + throw new SkippedException("Test is unstable with slowdebug bits"); + } + var tester = new TestRedirectLinks(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkPlatform/TestLinkPlatform.java b/test/langtools/jdk/javadoc/doclet/testLinkPlatform/TestLinkPlatform.java index 2d891f7b7cc..d9ea03e522d 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkPlatform/TestLinkPlatform.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkPlatform/TestLinkPlatform.java @@ -67,8 +67,8 @@ public class TestLinkPlatform extends JavadocTester { * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { - TestLinkPlatform tester = new TestLinkPlatform(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestLinkPlatform(); + tester.runTests(); } final ToolBox tb; diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkNotFound.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkNotFound.java index 47b4b379f97..cef3308fd6e 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkNotFound.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkNotFound.java @@ -39,7 +39,7 @@ public class TestLinkNotFound extends JavadocTester { public static void main(String... args) throws Exception { - TestLinkNotFound tester = new TestLinkNotFound(); + var tester = new TestLinkNotFound(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java index 5f294ce9748..54faadcee1e 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -38,7 +38,7 @@ public class TestLinkTaglet extends JavadocTester { public static void main(String... args) throws Exception { - TestLinkTaglet tester = new TestLinkTaglet(); + var tester = new TestLinkTaglet(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletPrimitive.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletPrimitive.java index f6308b7485f..3389007e04e 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletPrimitive.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletPrimitive.java @@ -40,7 +40,7 @@ public class TestLinkTagletPrimitive extends JavadocTester { public static void main(String... args) throws Exception { - TestLinkTagletPrimitive tester = new TestLinkTagletPrimitive(); + var tester = new TestLinkTagletPrimitive(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletWithModule.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletWithModule.java index 5d02d12f9e8..3adfe661965 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletWithModule.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletWithModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -50,8 +50,8 @@ public class TestLinkTagletWithModule extends JavadocTester { private final Path src; public static void main(String... args) throws Exception { - TestLinkTagletWithModule tester = new TestLinkTagletWithModule(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestLinkTagletWithModule(); + tester.runTests(); } TestLinkTagletWithModule() throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java b/test/langtools/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java index dfeb68dbfa7..c221c39e31d 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestLinkToSerialForm extends JavadocTester { public static void main(String... args) throws Exception { - TestLinkToSerialForm tester = new TestLinkToSerialForm(); + var tester = new TestLinkToSerialForm(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testLinksWithNoDeprecatedOption/TestLinksWithNoDeprecatedOption.java b/test/langtools/jdk/javadoc/doclet/testLinksWithNoDeprecatedOption/TestLinksWithNoDeprecatedOption.java index dbc36a3231a..aee2996be80 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinksWithNoDeprecatedOption/TestLinksWithNoDeprecatedOption.java +++ b/test/langtools/jdk/javadoc/doclet/testLinksWithNoDeprecatedOption/TestLinksWithNoDeprecatedOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -50,8 +50,8 @@ public class TestLinksWithNoDeprecatedOption extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestLinksWithNoDeprecatedOption tester = new TestLinksWithNoDeprecatedOption(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestLinksWithNoDeprecatedOption(); + tester.runTests(); } TestLinksWithNoDeprecatedOption() { diff --git a/test/langtools/jdk/javadoc/doclet/testLists/TestLists.java b/test/langtools/jdk/javadoc/doclet/testLists/TestLists.java index b1b25405dab..03aafb83869 100644 --- a/test/langtools/jdk/javadoc/doclet/testLists/TestLists.java +++ b/test/langtools/jdk/javadoc/doclet/testLists/TestLists.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -40,8 +40,8 @@ public class TestLists extends JavadocTester { public static void main(String... args) throws Exception { - TestLists tester = new TestLists(); - tester.runTests(m -> new Object[]{Path.of(m.getName())}); + var tester = new TestLists(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java b/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java index e70a8180673..b1885937831 100644 --- a/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java +++ b/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestLiteralCodeInPre extends JavadocTester { public static void main(String... args) throws Exception { - TestLiteralCodeInPre tester = new TestLiteralCodeInPre(); + var tester = new TestLiteralCodeInPre(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java index a372ab08da7..9955c93cb89 100644 --- a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,7 @@ public class TestMemberInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestMemberInheritance tester = new TestMemberInheritance(); + var tester = new TestMemberInheritance(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java b/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java index fc88182f479..6525e28bc87 100644 --- a/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java +++ b/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,7 +39,7 @@ public class TestMemberSummary extends JavadocTester { public static void main(String... args) throws Exception { - TestMemberSummary tester = new TestMemberSummary(); + var tester = new TestMemberSummary(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java b/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java index de9eeadf235..a7437bccd15 100644 --- a/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java +++ b/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java @@ -53,7 +53,7 @@ public class TestMetadata extends JavadocTester { public static void main(String... args) throws Exception { - TestMetadata tester = new TestMetadata(); + var tester = new TestMetadata(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMethodId/TestMethodId.java b/test/langtools/jdk/javadoc/doclet/testMethodId/TestMethodId.java index 20cedc70b01..7b198163236 100644 --- a/test/langtools/jdk/javadoc/doclet/testMethodId/TestMethodId.java +++ b/test/langtools/jdk/javadoc/doclet/testMethodId/TestMethodId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,8 +40,8 @@ public class TestMethodId extends JavadocTester { public static void main(String... args) throws Exception { - TestMethodId tester = new TestMethodId(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestMethodId(); + tester.runTests(); } private ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java b/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java index afb2e93a01f..bda82abddb6 100644 --- a/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java +++ b/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -36,7 +36,7 @@ public class TestMethodSignature extends JavadocTester { public static void main(String... args) throws Exception { - TestMethodSignature tester = new TestMethodSignature(); + var tester = new TestMethodSignature(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java b/test/langtools/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java index a9559fcd18e..b051af0902c 100644 --- a/test/langtools/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,7 +36,7 @@ public class TestMethodTypes extends JavadocTester { public static void main(String... args) throws Exception { - TestMethodTypes tester = new TestMethodTypes(); + var tester = new TestMethodTypes(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testMissingComment/TestMissingComment.java b/test/langtools/jdk/javadoc/doclet/testMissingComment/TestMissingComment.java index b5eaa7723fa..82238aa3a96 100644 --- a/test/langtools/jdk/javadoc/doclet/testMissingComment/TestMissingComment.java +++ b/test/langtools/jdk/javadoc/doclet/testMissingComment/TestMissingComment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -39,8 +39,8 @@ public class TestMissingComment extends JavadocTester { public static void main(String... args) throws Exception { - TestMissingComment tester = new TestMissingComment(); - tester.runTests(m -> new Object[] { Path.of(m.getName() )}); + var tester = new TestMissingComment(); + tester.runTests(); } private ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testMissingType/TestMissingType.java b/test/langtools/jdk/javadoc/doclet/testMissingType/TestMissingType.java index 4b998f616d8..a3c9b49dce0 100644 --- a/test/langtools/jdk/javadoc/doclet/testMissingType/TestMissingType.java +++ b/test/langtools/jdk/javadoc/doclet/testMissingType/TestMissingType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestMissingType extends JavadocTester { public static void main(String... args) throws Exception { - TestMissingType tester = new TestMissingType(); + var tester = new TestMissingType(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java b/test/langtools/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java index 326d7df8a1e..e0f005ff578 100644 --- a/test/langtools/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java +++ b/test/langtools/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -35,7 +35,7 @@ public class TestModifierEx extends JavadocTester { public static void main(String... args) throws Exception { - TestModifierEx tester = new TestModifierEx(); + var tester = new TestModifierEx(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java b/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java index 48f7bd2c633..612d94d0f83 100644 --- a/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java +++ b/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -47,8 +47,8 @@ public class TestModuleDirs extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestModuleDirs tester = new TestModuleDirs(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestModuleDirs(); + tester.runTests(); } public TestModuleDirs() { diff --git a/test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java b/test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java index b79be187406..48b4750573b 100644 --- a/test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -49,8 +49,8 @@ public class TestModuleSpecificStylesheet extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestModuleSpecificStylesheet tester = new TestModuleSpecificStylesheet(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestModuleSpecificStylesheet(); + tester.runTests(); } TestModuleSpecificStylesheet() { diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestEmptyModule.java b/test/langtools/jdk/javadoc/doclet/testModules/TestEmptyModule.java index 3320963613e..149f28a33be 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestEmptyModule.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestEmptyModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -45,8 +45,8 @@ public class TestEmptyModule extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestEmptyModule tester = new TestEmptyModule(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestEmptyModule(); + tester.runTests(); } public TestEmptyModule() { diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java b/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java index 91660d8da9d..22cb0da879b 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -45,8 +45,8 @@ public class TestIndirectExportsOpens extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestIndirectExportsOpens tester = new TestIndirectExportsOpens(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestIndirectExportsOpens(); + tester.runTests(); } public TestIndirectExportsOpens() { diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java index 5ca8ed88339..b2353809c8e 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java @@ -47,8 +47,8 @@ enum TabKind { EXPORTS, OPENS, CONCEALED }; enum ColKind { EXPORTED_TO, OPENED_TO }; public static void main(String... args) throws Exception { - TestModulePackages tester = new TestModulePackages(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestModulePackages(); + tester.runTests(); } private final ToolBox tb; diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java index ed965ee937d..aa393faaa25 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -46,8 +46,8 @@ public class TestModuleServices extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestModuleServices tester = new TestModuleServices(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestModuleServices(); + tester.runTests(); } public TestModuleServices() { diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java index 1e35f6352f2..fffec4cf4a7 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -45,8 +45,8 @@ public class TestModuleServicesLink extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestModuleServicesLink tester = new TestModuleServicesLink (); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestModuleServicesLink (); + tester.runTests(); } public TestModuleServicesLink () { diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java index 593d6c77994..51234bc3e19 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java @@ -39,7 +39,7 @@ public class TestModules extends JavadocTester { public static void main(String... args) throws Exception { - TestModules tester = new TestModules(); + var tester = new TestModules(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestModuleNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestModuleNavigation.java index f51c89d38c9..cf4da7d55ea 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestModuleNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestModuleNavigation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -46,8 +46,8 @@ public class TestModuleNavigation extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestModuleNavigation tester = new TestModuleNavigation (); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestModuleNavigation (); + tester.runTests(); } public TestModuleNavigation () { diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 4a78d0974f5..7dd8eaca2a1 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -44,8 +44,8 @@ public class TestNavigation extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestNavigation tester = new TestNavigation(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestNavigation(); + tester.runTests(); } public TestNavigation() { diff --git a/test/langtools/jdk/javadoc/doclet/testNestedClasses/TestNestedClasses.java b/test/langtools/jdk/javadoc/doclet/testNestedClasses/TestNestedClasses.java index 04fb1765801..a06f3453538 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedClasses/TestNestedClasses.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedClasses/TestNestedClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -47,8 +47,8 @@ public class TestNestedClasses extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedClasses tester = new TestNestedClasses(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestNestedClasses(); + tester.runTests(); tester.runLater(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java b/test/langtools/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java index f964262f7c2..b34574a592d 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,7 @@ public class TestNestedGenerics extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedGenerics tester = new TestNestedGenerics(); + var tester = new TestNestedGenerics(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedIndexTag.java b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedIndexTag.java index 899d6874034..6c1083fc89d 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedIndexTag.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedIndexTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -42,8 +42,8 @@ public class TestNestedIndexTag extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedIndexTag tester = new TestNestedIndexTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestNestedIndexTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedLinkTag.java b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedLinkTag.java index a20459bf928..e4e8f586844 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedLinkTag.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedLinkTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -42,8 +42,8 @@ public class TestNestedLinkTag extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedLinkTag tester = new TestNestedLinkTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestNestedLinkTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedReturnTag.java b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedReturnTag.java index f58ba04e904..49dfa196be2 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedReturnTag.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedReturnTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,8 +40,8 @@ public class TestNestedReturnTag extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedReturnTag tester = new TestNestedReturnTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestNestedReturnTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedSummaryTag.java b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedSummaryTag.java index 3d4e2a19b1b..860f2ecd29e 100644 --- a/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedSummaryTag.java +++ b/test/langtools/jdk/javadoc/doclet/testNestedInlineTags/TestNestedSummaryTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,8 +40,8 @@ public class TestNestedSummaryTag extends JavadocTester { public static void main(String... args) throws Exception { - TestNestedSummaryTag tester = new TestNestedSummaryTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestNestedSummaryTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java index 1163b1cb8ea..47b6dcffbfe 100644 --- a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,7 +39,7 @@ public class TestNewLanguageFeatures extends JavadocTester { public static void main(String... args) throws Exception { - TestNewLanguageFeatures tester = new TestNewLanguageFeatures(); + var tester = new TestNewLanguageFeatures(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNoFrames/TestNoFrames.java b/test/langtools/jdk/javadoc/doclet/testNoFrames/TestNoFrames.java index b367fb70a6e..2878b1b0f02 100644 --- a/test/langtools/jdk/javadoc/doclet/testNoFrames/TestNoFrames.java +++ b/test/langtools/jdk/javadoc/doclet/testNoFrames/TestNoFrames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -36,7 +36,7 @@ public class TestNoFrames extends JavadocTester { public static void main(String... args) throws Exception { - TestNoFrames tester = new TestNoFrames(); + var tester = new TestNoFrames(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java b/test/langtools/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java index e89d9664a19..9ccbe563cf9 100644 --- a/test/langtools/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java +++ b/test/langtools/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestNoPackagesFile extends JavadocTester { public static void main(String... args) throws Exception { - TestNoPackagesFile tester = new TestNoPackagesFile(); + var tester = new TestNoPackagesFile(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java index b0b54bbdd6c..4b211802841 100644 --- a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java +++ b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestNonInlineHtmlTagRemoval extends JavadocTester { public static void main(String... args) throws Exception { - TestNonInlineHtmlTagRemoval tester = new TestNonInlineHtmlTagRemoval(); + var tester = new TestNonInlineHtmlTagRemoval(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testNotifications/TestNotifications.java b/test/langtools/jdk/javadoc/doclet/testNotifications/TestNotifications.java index b3fed18a4c9..0ef59c72c81 100644 --- a/test/langtools/jdk/javadoc/doclet/testNotifications/TestNotifications.java +++ b/test/langtools/jdk/javadoc/doclet/testNotifications/TestNotifications.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -38,7 +38,7 @@ public class TestNotifications extends JavadocTester { public static void main(String... args) throws Exception { - TestNotifications tester = new TestNotifications(); + var tester = new TestNotifications(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java index e1e3bd2b7dc..13baea3b80c 100644 --- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java +++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -41,7 +41,7 @@ public class TestOptions extends JavadocTester { public static void main(String... args) throws Exception { - TestOptions tester = new TestOptions(); + var tester = new TestOptions(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java index c03a97cc59f..fca8f36aa9d 100644 --- a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java +++ b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -46,7 +46,7 @@ public class TestOrdering extends JavadocTester { public static void main(String[] args) throws Exception { - TestOrdering tester = new TestOrdering(); + var tester = new TestOrdering(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java index 896f15a73d4..6d8e61bd32f 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -40,7 +40,7 @@ public class TestBadOverride extends JavadocTester { * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { - TestBadOverride tester = new TestBadOverride(); + var tester = new TestBadOverride(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestMultiInheritance.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestMultiInheritance.java index cc844896f8e..ccd28448866 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestMultiInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestMultiInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,7 +37,7 @@ public class TestMultiInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestMultiInheritance tester = new TestMultiInheritance(); + var tester = new TestMultiInheritance(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenDeprecatedMethods.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenDeprecatedMethods.java index 31cbfb14fb1..23e56b22c5c 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenDeprecatedMethods.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenDeprecatedMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -36,7 +36,7 @@ public class TestOverriddenDeprecatedMethods extends JavadocTester { public static void main(String args[]) throws Exception { - TestOverriddenDeprecatedMethods tester = new TestOverriddenDeprecatedMethods(); + var tester = new TestOverriddenDeprecatedMethods(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenMethodDocCopy.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenMethodDocCopy.java index a2b96e19239..4106c151db9 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenMethodDocCopy.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenMethodDocCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -41,7 +41,7 @@ public class TestOverriddenMethodDocCopy extends JavadocTester { * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { - TestOverriddenMethodDocCopy tester = new TestOverriddenMethodDocCopy(); + var tester = new TestOverriddenMethodDocCopy(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethods.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethods.java index 5c4f7ad2c93..2bcfa0c47cb 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethods.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestOverriddenPrivateMethods extends JavadocTester { public static void main(String... args) throws Exception { - TestOverriddenPrivateMethods tester = new TestOverriddenPrivateMethods(); + var tester = new TestOverriddenPrivateMethods(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPackageFlag.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPackageFlag.java index 2cada0103b8..6a2d1013279 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPackageFlag.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPackageFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestOverriddenPrivateMethodsWithPackageFlag extends JavadocTester { public static void main(String... args) throws Exception { - TestOverriddenPrivateMethodsWithPackageFlag tester = new TestOverriddenPrivateMethodsWithPackageFlag(); + var tester = new TestOverriddenPrivateMethodsWithPackageFlag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPrivateFlag.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPrivateFlag.java index 36f579ed61b..16bc2a7f69a 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPrivateFlag.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverriddenPrivateMethodsWithPrivateFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestOverriddenPrivateMethodsWithPrivateFlag extends JavadocTester { public static void main(String... args) throws Exception { - TestOverriddenPrivateMethodsWithPrivateFlag tester = new TestOverriddenPrivateMethodsWithPrivateFlag(); + var tester = new TestOverriddenPrivateMethodsWithPrivateFlag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java index 4e358149669..198f04ff9ef 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java @@ -35,7 +35,7 @@ public class TestOverrideMethods extends JavadocTester { public static void main(String... args) throws Exception { - TestOverrideMethods tester = new TestOverrideMethods(); + var tester = new TestOverrideMethods(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverview/TestOverview.java b/test/langtools/jdk/javadoc/doclet/testOverview/TestOverview.java index b0dcaa7a687..6810d2dc74c 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverview/TestOverview.java +++ b/test/langtools/jdk/javadoc/doclet/testOverview/TestOverview.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -37,7 +37,7 @@ public class TestOverview extends JavadocTester { public static void main(String... args) throws Exception { - TestOverview tester = new TestOverview(); + var tester = new TestOverview(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java b/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java index f310fd55f39..bf56ec43c1d 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -36,7 +36,7 @@ public class TestPackageAnnotation extends JavadocTester { public static void main(String... args) throws Exception { - TestPackageAnnotation tester = new TestPackageAnnotation(); + var tester = new TestPackageAnnotation(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java b/test/langtools/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java index 474884d841a..03e9bf399f5 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,7 @@ public class TestPackageDeprecation extends JavadocTester { public static void main(String... args) throws Exception { - TestPackageDeprecation tester = new TestPackageDeprecation(); + var tester = new TestPackageDeprecation(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java b/test/langtools/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java index 3790767daf5..d35138bd3f3 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestPackageDescription extends JavadocTester { public static void main(String... args) throws Exception { - TestPackageDescription tester = new TestPackageDescription(); + var tester = new TestPackageDescription(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java b/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java index 15e72c4c664..205fd13d68a 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -35,7 +35,7 @@ public class TestPackageHtml extends JavadocTester { public static void main(String... args) throws Exception { - TestPackageHtml tester = new TestPackageHtml(); + var tester = new TestPackageHtml(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java b/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java index 16b33167f0a..f0edd0699a7 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java +++ b/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,7 @@ public class TestPackagePage extends JavadocTester { public static void main(String... args) throws Exception { - TestPackagePage tester = new TestPackagePage(); + var tester = new TestPackagePage(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java b/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java index 4befea3123d..9c6ddc5616d 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -47,8 +47,8 @@ public class TestPackageSpecificStylesheet extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestPackageSpecificStylesheet tester = new TestPackageSpecificStylesheet(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestPackageSpecificStylesheet(); + tester.runTests(); } TestPackageSpecificStylesheet() { diff --git a/test/langtools/jdk/javadoc/doclet/testPackageSummary/TestPackageSummary.java b/test/langtools/jdk/javadoc/doclet/testPackageSummary/TestPackageSummary.java index 65dbbf743d5..599bac5d6ef 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageSummary/TestPackageSummary.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageSummary/TestPackageSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -38,7 +38,7 @@ public class TestPackageSummary extends JavadocTester { public static void main(String... args) throws Exception { - TestPackageSummary tester = new TestPackageSummary(); + var tester = new TestPackageSummary(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java b/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java index 200af37a948..b2364aba201 100644 --- a/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java @@ -38,7 +38,7 @@ public class TestParamTaglet extends JavadocTester { public static void main(String... args) throws Exception { - TestParamTaglet tester = new TestParamTaglet(); + var tester = new TestParamTaglet(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index b4c6e487135..75fa87ae3e3 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java @@ -38,7 +38,7 @@ public class TestPreview extends JavadocTester { public static void main(String... args) throws Exception { - TestPreview tester = new TestPreview(); + var tester = new TestPreview(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java index 9b23a45a2dd..bf715f895a3 100644 --- a/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java +++ b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java @@ -46,7 +46,7 @@ public class TestPrivateClasses extends JavadocTester { public static void main(String... args) throws Exception { - TestPrivateClasses tester = new TestPrivateClasses(); + var tester = new TestPrivateClasses(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java index 394fa3483b7..240cddf2d6c 100644 --- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java +++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestProperty extends JavadocTester { public static void main(String... args) throws Exception { - TestProperty tester = new TestProperty(); + var tester = new TestProperty(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java b/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java index 8cd2cb6ca2c..4f25eff6e59 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordLinks/TestRecordLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -38,8 +38,8 @@ public class TestRecordLinks extends JavadocTester { public static void main(String... args) throws Exception { - TestRecordLinks tester = new TestRecordLinks(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestRecordLinks(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java index c5820d68796..c4579c501ec 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java @@ -45,8 +45,8 @@ public class TestRecordTypes extends JavadocTester { public static void main(String... args) throws Exception { - TestRecordTypes tester = new TestRecordTypes(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestRecordTypes(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java b/test/langtools/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java index 6d921367fcd..4d8f7adb2c6 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java +++ b/test/langtools/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestRecurseSubPackages extends JavadocTester { public static void main(String... args) throws Exception { - TestRecurseSubPackages tester = new TestRecurseSubPackages(); + var tester = new TestRecurseSubPackages(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testRelatedPackages/TestRelatedPackages.java b/test/langtools/jdk/javadoc/doclet/testRelatedPackages/TestRelatedPackages.java index 8ef2c131b4e..3793b079fa8 100644 --- a/test/langtools/jdk/javadoc/doclet/testRelatedPackages/TestRelatedPackages.java +++ b/test/langtools/jdk/javadoc/doclet/testRelatedPackages/TestRelatedPackages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -45,8 +45,8 @@ public class TestRelatedPackages extends JavadocTester { ToolBox tb = new ToolBox(); public static void main(String... args) throws Exception { - TestRelatedPackages tester = new TestRelatedPackages(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestRelatedPackages(); + tester.runTests(); } @Test diff --git a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java index b0e1c76a11b..f8b6e9186cd 100644 --- a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java @@ -44,7 +44,7 @@ public class TestRelativeLinks extends JavadocTester { public static void main(String... args) throws Exception { - TestRelativeLinks tester = new TestRelativeLinks(); + var tester = new TestRelativeLinks(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeModuleLinks.java b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeModuleLinks.java index ff645b999cf..14057cabaca 100644 --- a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeModuleLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeModuleLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -46,8 +46,8 @@ public class TestRelativeModuleLinks extends JavadocTester { public final ToolBox tb; public static void main(String... args) throws Exception { - TestRelativeModuleLinks tester = new TestRelativeModuleLinks(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestRelativeModuleLinks(); + tester.runTests(); } public TestRelativeModuleLinks() { diff --git a/test/langtools/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java b/test/langtools/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java index dcd45191a24..274dd1a463a 100644 --- a/test/langtools/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java +++ b/test/langtools/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,7 +36,7 @@ public class TestRepeatedAnnotations extends JavadocTester { public static void main(String... args) throws Exception { - TestRepeatedAnnotations tester = new TestRepeatedAnnotations(); + var tester = new TestRepeatedAnnotations(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testReporterStreams/TestReporterStreams.java b/test/langtools/jdk/javadoc/doclet/testReporterStreams/TestReporterStreams.java index 06ace84888a..8621e60d399 100644 --- a/test/langtools/jdk/javadoc/doclet/testReporterStreams/TestReporterStreams.java +++ b/test/langtools/jdk/javadoc/doclet/testReporterStreams/TestReporterStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -59,8 +59,8 @@ public class TestReporterStreams extends JavadocTester { public static void main(String... args) throws Exception { - TestReporterStreams tester = new TestReporterStreams(); - tester.runTests(m -> new Object[]{Path.of(m.getName())}); + var tester = new TestReporterStreams(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java index 4974f4e586e..ceffa141609 100644 --- a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java +++ b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java @@ -40,8 +40,8 @@ public class TestReturnTag extends JavadocTester { public static void main(String... args) throws Exception { - TestReturnTag tester = new TestReturnTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestReturnTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java b/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java index 8112b286891..60731d2fa2a 100644 --- a/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -40,8 +40,8 @@ public class TestSealedTypes extends JavadocTester { public static void main(String... args) throws Exception { - TestSealedTypes tester = new TestSealedTypes(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestSealedTypes(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java index b3798184ac9..af343f656e8 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java +++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java @@ -45,7 +45,7 @@ public class TestSearch extends JavadocTester { public static void main(String... args) throws Exception { - TestSearch tester = new TestSearch(); + var tester = new TestSearch(); tester.runTests(); } @@ -423,7 +423,7 @@ void checkSearchOutput(String fileName, boolean expectedOutput, boolean moduleDi """, """ - + """, """ """, @@ -695,7 +695,7 @@ void checkInvalidUsageIndexTag() { void checkJqueryAndImageFiles(boolean expectedOutput) { checkFiles(expectedOutput, "search.js", - "script-dir/jquery-3.6.0.min.js", + "script-dir/jquery-3.6.1.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", "resources/x.png", diff --git a/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java b/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java index 9f17329c4a8..658d555cf66 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java +++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java @@ -55,7 +55,7 @@ public class TestSearchScript extends JavadocTester { public static void main(String... args) throws Exception { - TestSearchScript tester = new TestSearchScript(); + var tester = new TestSearchScript(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSeeLinkAnchor/TestSeeLinkAnchor.java b/test/langtools/jdk/javadoc/doclet/testSeeLinkAnchor/TestSeeLinkAnchor.java index 189e43fc304..b19d8009399 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeLinkAnchor/TestSeeLinkAnchor.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeLinkAnchor/TestSeeLinkAnchor.java @@ -50,8 +50,8 @@ public class TestSeeLinkAnchor extends JavadocTester { private final Path src; public static void main(String... args) throws Exception { - TestSeeLinkAnchor tester = new TestSeeLinkAnchor(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestSeeLinkAnchor(); + tester.runTests(); } TestSeeLinkAnchor() throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index 6052ad50df2..892ed458694 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java @@ -40,7 +40,7 @@ public class TestSeeTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSeeTag tester = new TestSeeTag(); + var tester = new TestSeeTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTagWithModule.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTagWithModule.java index fe4e87bd41a..6864aca1959 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTagWithModule.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTagWithModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -50,8 +50,8 @@ public class TestSeeTagWithModule extends JavadocTester { private final Path src; public static void main(String... args) throws Exception { - TestSeeTagWithModule tester = new TestSeeTagWithModule(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestSeeTagWithModule(); + tester.runTests(); } TestSeeTagWithModule() throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testSerialMissing/TestSerialMissing.java b/test/langtools/jdk/javadoc/doclet/testSerialMissing/TestSerialMissing.java index b0210468dc5..2abe2d9de0a 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerialMissing/TestSerialMissing.java +++ b/test/langtools/jdk/javadoc/doclet/testSerialMissing/TestSerialMissing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -41,8 +41,8 @@ public class TestSerialMissing extends JavadocTester { public static void main(String... args) throws Exception { - TestSerialMissing tester = new TestSerialMissing(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) } ); + var tester = new TestSerialMissing(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testSerialTag/TestSerialTag.java b/test/langtools/jdk/javadoc/doclet/testSerialTag/TestSerialTag.java index e93aab0d1e7..81b7df29d39 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerialTag/TestSerialTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSerialTag/TestSerialTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -40,8 +40,8 @@ public class TestSerialTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSerialTag tester = new TestSerialTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestSerialTag(); + tester.runTests(); } private final ToolBox tb; diff --git a/test/langtools/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java b/test/langtools/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java index 541c6957a9b..6a0cdb4e0a1 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java +++ b/test/langtools/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestSerialVersionUID extends JavadocTester { public static void main(String... args) throws Exception { - TestSerialVersionUID tester = new TestSerialVersionUID(); + var tester = new TestSerialVersionUID(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSerialWithLink/TestSerialWithLink.java b/test/langtools/jdk/javadoc/doclet/testSerialWithLink/TestSerialWithLink.java index 3940c9604a5..f4c885bc1e8 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerialWithLink/TestSerialWithLink.java +++ b/test/langtools/jdk/javadoc/doclet/testSerialWithLink/TestSerialWithLink.java @@ -39,7 +39,7 @@ public class TestSerialWithLink extends JavadocTester { public static void main(String... args) throws Exception { - TestSerialWithLink tester = new TestSerialWithLink(); + var tester = new TestSerialWithLink(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java index 777ad551425..9bf2ac362c6 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -42,7 +42,7 @@ public class TestSerializedForm extends JavadocTester { public static void main(String... args) throws Exception { - TestSerializedForm tester = new TestSerializedForm(); + var tester = new TestSerializedForm(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java b/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java index 64d2f9433e8..b79634943c1 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester { public static void main(String... args) throws Exception { - TestSerializedFormDeprecationInfo tester = new TestSerializedFormDeprecationInfo(); + var tester = new TestSerializedFormDeprecationInfo(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java index 5dc0de13de4..25613dffd95 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -50,8 +50,8 @@ public class TestSerializedFormWithClassFile extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestSerializedFormWithClassFile tester = new TestSerializedFormWithClassFile(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestSerializedFormWithClassFile(); + tester.runTests(); } TestSerializedFormWithClassFile() { diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithSee/TestSerializedFormWithSee.java b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithSee/TestSerializedFormWithSee.java index 42f6e6527b9..deb1566a589 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithSee/TestSerializedFormWithSee.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithSee/TestSerializedFormWithSee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -51,8 +51,8 @@ public class TestSerializedFormWithSee extends JavadocTester { public static void main(String... args) throws Exception { - TestSerializedFormWithSee tester = new TestSerializedFormWithSee(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestSerializedFormWithSee(); + tester.runTests(); } private final ToolBox tb; diff --git a/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java b/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java index ba48111b043..47f5bd832a9 100644 --- a/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class TestSimpleTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSimpleTag tester = new TestSimpleTag(); + var tester = new TestSimpleTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java b/test/langtools/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java index d275e70264f..7c6dc2f20be 100644 --- a/test/langtools/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java +++ b/test/langtools/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestSimpleTagExclude extends JavadocTester { public static void main(String... args) throws Exception { - TestSimpleTagExclude tester = new TestSimpleTagExclude(); + var tester = new TestSimpleTagExclude(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java b/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java index e5b67b03e42..d2f0695bf51 100644 --- a/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java +++ b/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java @@ -36,7 +36,7 @@ public class TestSimpleTagInherit extends JavadocTester { public static void main(String... args) throws Exception { - TestSimpleTagInherit tester = new TestSimpleTagInherit(); + var tester = new TestSimpleTagInherit(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java b/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java index b25c56bc25e..5f47be2c09a 100644 --- a/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,7 +36,7 @@ public class TestSinceTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSinceTag tester = new TestSinceTag(); + var tester = new TestSinceTag(); tester.runTests(); tester.printSummary(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java b/test/langtools/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java index 70fd741b013..e13d590d101 100644 --- a/test/langtools/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java +++ b/test/langtools/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -35,7 +35,7 @@ public class TestSingleQuotedLink extends JavadocTester { public static void main(String... args) throws Exception { - TestSingleQuotedLink tester = new TestSingleQuotedLink(); + var tester = new TestSingleQuotedLink(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java index a0d4a6f6267..30af0a37a54 100644 --- a/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java +++ b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -53,7 +53,7 @@ public class TestSingletonLists extends JavadocTester { public static void main(String... args) throws Exception { - TestSingletonLists tester = new TestSingletonLists(); + var tester = new TestSingletonLists(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java index de8ea1b3490..49b328f314d 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -44,7 +44,7 @@ public class TestLangProperties extends SnippetTester { public static void main(String... args) throws Exception { - new TestLangProperties().runTests(m -> new Object[]{Paths.get(m.getName())}); + new TestLangProperties().runTests(); } @Test diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java index f8957d62985..ed9b1dc7cb5 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java @@ -73,7 +73,7 @@ public class TestSnippetMarkup extends SnippetTester { public static void main(String... args) throws Exception { - new TestSnippetMarkup().runTests(m -> new Object[]{Paths.get(m.getName())}); + new TestSnippetMarkup().runTests(); } /* diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetPathOption.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetPathOption.java index 208faa45a4b..453736c02a0 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetPathOption.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetPathOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -43,7 +43,7 @@ public class TestSnippetPathOption extends SnippetTester { public static void main(String... args) throws Exception { - new TestSnippetPathOption().runTests(m -> new Object[]{Paths.get(m.getName())}); + new TestSnippetPathOption().runTests(); } /* diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java index 9923a191a57..70b0397c121 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java @@ -85,7 +85,7 @@ public class TestSnippetTag extends SnippetTester { public static void main(String... args) throws Exception { - new TestSnippetTag().runTests(m -> new Object[]{Paths.get(m.getName())}); + new TestSnippetTag().runTests(); } /* diff --git a/test/langtools/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java b/test/langtools/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java index ba6b339fd76..bae030d2ee7 100644 --- a/test/langtools/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java +++ b/test/langtools/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ public class TestSourceTab extends JavadocTester { public static void main(String... args) throws Exception { - TestSourceTab tester = new TestSourceTab(); + var tester = new TestSourceTab(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java b/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java index 74cc05c665f..724fc8373a3 100644 --- a/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java @@ -41,8 +41,8 @@ public class TestSpecTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSpecTag tester = new TestSpecTag(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestSpecTag(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java index dcdf0da48f3..8c729c8d3ec 100644 --- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java @@ -49,8 +49,8 @@ public class TestStylesheet extends JavadocTester { public static void main(String... args) throws Exception { - TestStylesheet tester = new TestStylesheet(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestStylesheet(); + tester.runTests(); } @Test diff --git a/test/langtools/jdk/javadoc/doclet/testStylesheetOverwrite/TestStylesheetOverwrite.java b/test/langtools/jdk/javadoc/doclet/testStylesheetOverwrite/TestStylesheetOverwrite.java index 0571a8266de..55124e91b4e 100644 --- a/test/langtools/jdk/javadoc/doclet/testStylesheetOverwrite/TestStylesheetOverwrite.java +++ b/test/langtools/jdk/javadoc/doclet/testStylesheetOverwrite/TestStylesheetOverwrite.java @@ -1,4 +1,4 @@ -/* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +/* * Copyright (c) 2018, 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 @@ -44,8 +44,8 @@ public class TestStylesheetOverwrite extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestStylesheetOverwrite tester = new TestStylesheetOverwrite(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestStylesheetOverwrite(); + tester.runTests(); } TestStylesheetOverwrite() { diff --git a/test/langtools/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java b/test/langtools/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java index bef74dee06b..53ab2342e88 100644 --- a/test/langtools/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java +++ b/test/langtools/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,7 @@ public class TestSubTitle extends JavadocTester { public static void main(String... args) throws Exception { - TestSubTitle tester = new TestSubTitle(); + var tester = new TestSubTitle(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java b/test/langtools/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java index 56b2446dc2b..822f703c7dc 100644 --- a/test/langtools/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java +++ b/test/langtools/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -38,7 +38,7 @@ public class TestSummaryHeading extends JavadocTester { public static void main(String... args) throws Exception { - TestSummaryHeading tester = new TestSummaryHeading(); + var tester = new TestSummaryHeading(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java index 1f8e1d7455b..6b348af9c7a 100644 --- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestSummaryTag extends JavadocTester { public static void main(String... args) throws Exception { - TestSummaryTag tester = new TestSummaryTag(); + var tester = new TestSummaryTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java b/test/langtools/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java index 803dd283971..d3f1f139763 100644 --- a/test/langtools/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java +++ b/test/langtools/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestSuperClassInSerialForm extends JavadocTester { public static void main(String... args) throws Exception { - TestSuperClassInSerialForm tester = new TestSuperClassInSerialForm(); + var tester = new TestSuperClassInSerialForm(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java b/test/langtools/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java index 8d5c80762d7..d65ed78eace 100644 --- a/test/langtools/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java +++ b/test/langtools/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -41,7 +41,7 @@ public class TestSupplementary extends JavadocTester { public static void main(String... args) throws Exception { Locale saveLocale = Locale.getDefault(); try { - TestSupplementary tester = new TestSupplementary(); + var tester = new TestSupplementary(); tester.runTests(); } finally { Locale.setDefault(saveLocale); diff --git a/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java b/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java index 0cc6c6de4c1..75bef1d4c81 100644 --- a/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java +++ b/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -42,8 +42,8 @@ public class TestSystemPropertyPage extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestSystemPropertyPage tester = new TestSystemPropertyPage(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestSystemPropertyPage(); + tester.runTests(); } TestSystemPropertyPage() { diff --git a/test/langtools/jdk/javadoc/doclet/testSystemPropertyTaglet/TestSystemPropertyTaglet.java b/test/langtools/jdk/javadoc/doclet/testSystemPropertyTaglet/TestSystemPropertyTaglet.java index d109294b170..0bf2e5876cc 100644 --- a/test/langtools/jdk/javadoc/doclet/testSystemPropertyTaglet/TestSystemPropertyTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testSystemPropertyTaglet/TestSystemPropertyTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -45,8 +45,8 @@ public class TestSystemPropertyTaglet extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestSystemPropertyTaglet tester = new TestSystemPropertyTaglet(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestSystemPropertyTaglet(); + tester.runTests(); } TestSystemPropertyTaglet() { diff --git a/test/langtools/jdk/javadoc/doclet/testTagInheritance/TestTagInheritance.java b/test/langtools/jdk/javadoc/doclet/testTagInheritance/TestTagInheritance.java index 67fecce52aa..7fc9eb8b519 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagInheritance/TestTagInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testTagInheritance/TestTagInheritance.java @@ -36,7 +36,7 @@ public class TestTagInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestTagInheritance tester = new TestTagInheritance(); + var tester = new TestTagInheritance(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java b/test/langtools/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java index 6d879bbab97..ebdf11328a7 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java +++ b/test/langtools/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java @@ -41,7 +41,7 @@ public class TestTagMisuse extends JavadocTester { * @throws Exception if the test fails */ public static void main(String... args) throws Exception { - TestTagMisuse tester = new TestTagMisuse(); + var tester = new TestTagMisuse(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTagOrder/TestTagOrder.java b/test/langtools/jdk/javadoc/doclet/testTagOrder/TestTagOrder.java index 5431e384d93..74d81ba4cf3 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagOrder/TestTagOrder.java +++ b/test/langtools/jdk/javadoc/doclet/testTagOrder/TestTagOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -53,8 +53,8 @@ */ public class TestTagOrder extends JavadocTester { public static void main(String... args) throws Exception { - TestTagOrder tester = new TestTagOrder(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestTagOrder(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java b/test/langtools/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java index 5fd50cfd400..35989e021e4 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java +++ b/test/langtools/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,7 +36,7 @@ public class TestTagOutput extends JavadocTester { public static void main(String... args) throws Exception { - TestTagOutput tester = new TestTagOutput(); + var tester = new TestTagOutput(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTaglets/TestTaglets.java b/test/langtools/jdk/javadoc/doclet/testTaglets/TestTaglets.java index d76a425a976..56d409a4c86 100644 --- a/test/langtools/jdk/javadoc/doclet/testTaglets/TestTaglets.java +++ b/test/langtools/jdk/javadoc/doclet/testTaglets/TestTaglets.java @@ -50,7 +50,7 @@ public class TestTaglets extends JavadocTester { public static void main(String... args) throws Exception { - TestTaglets tester = new TestTaglets(); + var tester = new TestTaglets(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTerminology/TestTerminology.java b/test/langtools/jdk/javadoc/doclet/testTerminology/TestTerminology.java index 47b8dd0d972..d29844000ae 100644 --- a/test/langtools/jdk/javadoc/doclet/testTerminology/TestTerminology.java +++ b/test/langtools/jdk/javadoc/doclet/testTerminology/TestTerminology.java @@ -40,8 +40,8 @@ public class TestTerminology extends JavadocTester { public static void main(String... args) throws Exception { - TestTerminology tester = new TestTerminology(); - tester.runTests(m -> new Object[]{Path.of(m.getName())}); + var tester = new TestTerminology(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java index 57e88d60c9e..ca4592ea5f8 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java +++ b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -42,8 +42,8 @@ public class TestThrows extends JavadocTester { public static void main(String... args) throws Exception { - TestThrows tester = new TestThrows(); - tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + var tester = new TestThrows(); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java b/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java index 378f297bd53..faa87feb590 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,7 @@ public class TestThrowsHead extends JavadocTester { public static void main(String... args) throws Exception { - TestThrowsHead tester = new TestThrowsHead(); + var tester = new TestThrowsHead(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java index 6e9b58df692..cf7f365d9b2 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java @@ -38,7 +38,7 @@ public class TestThrowsTagInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestThrowsTagInheritance tester = new TestThrowsTagInheritance(); + var tester = new TestThrowsTagInheritance(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMatching/TestExceptionTypeMatching.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMatching/TestExceptionTypeMatching.java index 73f75580da1..0e66b808f06 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMatching/TestExceptionTypeMatching.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMatching/TestExceptionTypeMatching.java @@ -50,7 +50,7 @@ public class TestExceptionTypeMatching extends JavadocTester { public static void main(String... args) throws Exception { var tester = new TestExceptionTypeMatching(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMultiple/TestOneToMany.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMultiple/TestOneToMany.java index f33539f80fa..a315ffe3399 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMultiple/TestOneToMany.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsInheritanceMultiple/TestOneToMany.java @@ -42,7 +42,7 @@ public class TestOneToMany extends JavadocTester { public static void main(String... args) throws Exception { var tester = new TestOneToMany(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + tester.runTests(); } private final ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java b/test/langtools/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java index 0a4bef6b4a6..5b09ca980e5 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -37,7 +37,7 @@ public class TestThrowsTag extends JavadocTester { public static void main(String... args) throws Exception { - TestThrowsTag tester = new TestThrowsTag(); + var tester = new TestThrowsTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java b/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java index 700f2956da9..98ffc9e99a4 100644 --- a/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java +++ b/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestTitleInHref extends JavadocTester { public static void main(String... args) throws Exception { - TestTitleInHref tester = new TestTitleInHref(); + var tester = new TestTitleInHref(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java b/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java index 377d8498931..353e3c0842c 100644 --- a/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java +++ b/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -36,7 +36,7 @@ public class TestTopOption extends JavadocTester { public static void main(String... args) throws Exception { - TestTopOption tester = new TestTopOption(); + var tester = new TestTopOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java b/test/langtools/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java index 6fcbceed9a8..02d011906cd 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -37,7 +37,7 @@ public class TestTypeAnnotations extends JavadocTester { public static void main(String... args) throws Exception { - TestTypeAnnotations tester = new TestTypeAnnotations(); + var tester = new TestTypeAnnotations(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java index a548facfd54..7f586b3539d 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -40,7 +40,7 @@ public class TestTypeParameters extends JavadocTester { public static void main(String... args) throws Exception { - TestTypeParameters tester = new TestTypeParameters(); + var tester = new TestTypeParameters(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeVariableLinks/TestTypeVariableLinks.java b/test/langtools/jdk/javadoc/doclet/testTypeVariableLinks/TestTypeVariableLinks.java index 913f2d3ae98..0c14f41c08a 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeVariableLinks/TestTypeVariableLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeVariableLinks/TestTypeVariableLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestTypeVariableLinks extends JavadocTester { public static void main(String... args) throws Exception { - TestTypeVariableLinks tester = new TestTypeVariableLinks(); + var tester = new TestTypeVariableLinks(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java index 9621c18b760..e08ef6833bf 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java +++ b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -40,8 +40,8 @@ public class TestUnicode extends JavadocTester { public static void main(String... args) throws Exception { - TestUnicode tester = new TestUnicode(); - tester.runTests(m -> new Object[] { Path.of(m.getName())}); + var tester = new TestUnicode(); + tester.runTests(); } ToolBox tb = new ToolBox(); diff --git a/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java b/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java index 9f9dce38a64..688d89ee2d0 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java +++ b/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -38,7 +38,7 @@ public class TestUnnamedPackage extends JavadocTester { public static void main(String... args) throws Exception { - TestUnnamedPackage tester = new TestUnnamedPackage(); + var tester = new TestUnnamedPackage(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java b/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java index a656d8b3345..ed96377c7e3 100644 --- a/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java +++ b/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestUseOption extends JavadocTester { public static void main(String... args) throws Exception { - TestUseOption tester = new TestUseOption(); + var tester = new TestUseOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testUserTaglet/TestUserTaglet.java b/test/langtools/jdk/javadoc/doclet/testUserTaglet/TestUserTaglet.java index 1cdee23ad4b..02ecaafde18 100644 --- a/test/langtools/jdk/javadoc/doclet/testUserTaglet/TestUserTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testUserTaglet/TestUserTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestUserTaglet extends JavadocTester { public static void main(String... args) throws Exception { - TestUserTaglet tester = new TestUserTaglet(); + var tester = new TestUserTaglet(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueFormats.java b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueFormats.java index 3d382cda900..a4aad3934bb 100644 --- a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueFormats.java +++ b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueFormats.java @@ -46,8 +46,8 @@ public class TestValueFormats extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestValueFormats tester = new TestValueFormats(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestValueFormats(); + tester.runTests(); } TestValueFormats() { diff --git a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java index 6197c18671c..ce42a8b7f77 100644 --- a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java +++ b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -43,7 +43,7 @@ public class TestValueTag extends JavadocTester { public static void main(String... args) throws Exception { - TestValueTag tester = new TestValueTag(); + var tester = new TestValueTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java index 5cf85711122..5173455412d 100644 --- a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java +++ b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -47,8 +47,8 @@ public class TestValueTagInModule extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestValueTagInModule tester = new TestValueTagInModule(); - tester.runTests(m -> new Object[]{Paths.get(m.getName())}); + var tester = new TestValueTagInModule(); + tester.runTests(); } TestValueTagInModule() { diff --git a/test/langtools/jdk/javadoc/doclet/testVersionOption/TestVersionOption.java b/test/langtools/jdk/javadoc/doclet/testVersionOption/TestVersionOption.java index bd337276582..cf7e40a0cad 100644 --- a/test/langtools/jdk/javadoc/doclet/testVersionOption/TestVersionOption.java +++ b/test/langtools/jdk/javadoc/doclet/testVersionOption/TestVersionOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ public class TestVersionOption extends JavadocTester { public static void main(String... args) throws Exception { - TestVersionOption tester = new TestVersionOption(); + var tester = new TestVersionOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java b/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java index a244fb9f70c..e04fa956e74 100644 --- a/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java +++ b/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java @@ -42,7 +42,7 @@ public class TestVersionTag extends JavadocTester { public static void main(String... args) throws Exception { - TestVersionTag tester = new TestVersionTag(); + var tester = new TestVersionTag(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java index 5e505d186c6..09f6f92e2b6 100644 --- a/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java +++ b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java @@ -49,8 +49,8 @@ public class TestVisibleMembers extends JavadocTester { final ToolBox tb; public static void main(String... args) throws Exception { - TestVisibleMembers tester = new TestVisibleMembers(); - tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + var tester = new TestVisibleMembers(); + tester.runTests(); } TestVisibleMembers() { diff --git a/test/langtools/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java b/test/langtools/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java index 2a8ea04e8d0..0929da5f857 100644 --- a/test/langtools/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java +++ b/test/langtools/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,7 +37,7 @@ public class TestWarnBadParamNames extends JavadocTester { public static void main(String... args) throws Exception { - TestWarnBadParamNames tester = new TestWarnBadParamNames(); + var tester = new TestWarnBadParamNames(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testWarnings/TestWarnings.java b/test/langtools/jdk/javadoc/doclet/testWarnings/TestWarnings.java index 1c5c3ba686e..e33776a7af5 100644 --- a/test/langtools/jdk/javadoc/doclet/testWarnings/TestWarnings.java +++ b/test/langtools/jdk/javadoc/doclet/testWarnings/TestWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -39,7 +39,7 @@ public class TestWarnings extends JavadocTester { public static void main(String... args) throws Exception { - TestWarnings tester = new TestWarnings(); + var tester = new TestWarnings(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java b/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java index 3c65066419c..4e5f9f7e519 100644 --- a/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java +++ b/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java @@ -39,7 +39,7 @@ public class TestXOption extends JavadocTester { public static void main(String... args) throws Exception { - TestXOption tester = new TestXOption(); + var tester = new TestXOption(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java b/test/langtools/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java index bf0e0aa599e..6ff6b3440dd 100644 --- a/test/langtools/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java +++ b/test/langtools/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -37,7 +37,7 @@ public class TestSmoke extends JavadocTester { public static void main(String... args) throws Exception { - TestSmoke tester = new TestSmoke(); + var tester = new TestSmoke(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java index f4bd008d061..dd0cc3c1f4a 100644 --- a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java +++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java @@ -97,7 +97,7 @@ *
    
      *  public class MyTester extends JavadocTester {
      *      public static void main(String... args) throws Exception {
    - *          MyTester tester = new MyTester();
    + *          var tester = new MyTester();
      *          tester.runTests();
      *      }
      *
    diff --git a/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTester.java b/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTester.java
    index 238c12dcfe5..2fcb0c9a958 100644
    --- a/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTester.java
    +++ b/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTester.java
    @@ -59,7 +59,7 @@
      */
     public class TestJavadocTester extends JavadocTester {
         public static void main(String... args) throws Exception {
    -        TestJavadocTester tester = new TestJavadocTester();
    +        var tester = new TestJavadocTester();
             tester.setup().runTests();
         }
     
    diff --git a/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTesterCrash.java b/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTesterCrash.java
    index f0069f32f53..f0a6b0e98eb 100644
    --- a/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTesterCrash.java
    +++ b/test/langtools/jdk/javadoc/testJavadocTester/TestJavadocTesterCrash.java
    @@ -58,7 +58,7 @@
      */
     public class TestJavadocTesterCrash extends TestJavadocTester {
         public static void main(String... args) throws Exception {
    -        TestJavadocTesterCrash tester = new TestJavadocTesterCrash();
    +        var tester = new TestJavadocTesterCrash();
             tester.runTests();
         }
     
    diff --git a/test/langtools/jdk/javadoc/testTFMBuilder/TestTFMBuilder.java b/test/langtools/jdk/javadoc/testTFMBuilder/TestTFMBuilder.java
    index 209eb496e3f..b3f498b0d6a 100644
    --- a/test/langtools/jdk/javadoc/testTFMBuilder/TestTFMBuilder.java
    +++ b/test/langtools/jdk/javadoc/testTFMBuilder/TestTFMBuilder.java
    @@ -67,8 +67,8 @@ public static class TestException extends RuntimeException {
         }
     
         public static void main(String... args) throws Exception {
    -        TestTFMBuilder tester = new TestTFMBuilder();
    -        tester.setup().runTests(m -> new Object[] { Path.of(m.getName()) });
    +        var tester = new TestTFMBuilder();
    +        tester.setup().runTests();
         }
     
         private Path srcDir = Path.of("src");
    diff --git a/test/langtools/jdk/javadoc/tool/8224612/OptionsTest.java b/test/langtools/jdk/javadoc/tool/8224612/OptionsTest.java
    index 15157962448..bc528eb884a 100644
    --- a/test/langtools/jdk/javadoc/tool/8224612/OptionsTest.java
    +++ b/test/langtools/jdk/javadoc/tool/8224612/OptionsTest.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2020, 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
    @@ -52,7 +52,7 @@
     public class OptionsTest extends JavadocTester {
     
         public static void main(String... args) throws Exception {
    -        new OptionsTest().runTests(m -> new Object[]{Paths.get(m.getName())});
    +        new OptionsTest().runTests();
         }
     
         @Test
    diff --git a/test/langtools/jdk/javadoc/tool/8224613/OptionProcessingFailureTest.java b/test/langtools/jdk/javadoc/tool/8224613/OptionProcessingFailureTest.java
    index c2fc29cfbd2..1ee78cba649 100644
    --- a/test/langtools/jdk/javadoc/tool/8224613/OptionProcessingFailureTest.java
    +++ b/test/langtools/jdk/javadoc/tool/8224613/OptionProcessingFailureTest.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2020, 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
    @@ -79,7 +79,7 @@ public class OptionProcessingFailureTest extends JavadocTester {
         private final ToolBox tb = new ToolBox();
     
         public static void main(String... args) throws Exception {
    -        new OptionProcessingFailureTest().runTests(m -> new Object[]{Paths.get(m.getName())});
    +        new OptionProcessingFailureTest().runTests();
         }
     
         @Test
    diff --git a/test/langtools/jdk/javadoc/tool/CommandLineHelpTest.java b/test/langtools/jdk/javadoc/tool/CommandLineHelpTest.java
    index 60b25e3220d..aa644eccf40 100644
    --- a/test/langtools/jdk/javadoc/tool/CommandLineHelpTest.java
    +++ b/test/langtools/jdk/javadoc/tool/CommandLineHelpTest.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2020, 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
    @@ -37,8 +37,8 @@
     
     public class CommandLineHelpTest extends JavadocTester {
         public static void main(String... args) throws Exception {
    -        CommandLineHelpTest tester = new CommandLineHelpTest();
    -        tester.runTests(m -> new Object[] { Path.of(m.getName()) });
    +        var tester = new CommandLineHelpTest();
    +        tester.runTests();
         }
     
         @Test
    diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java
    index 75c9ce61db9..787f8a93d8c 100644
    --- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java
    +++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java
    @@ -201,7 +201,7 @@ protected void error(String msg) {
                 "help-doc.html",
                 "index-all.html",
                 "index.html",
    -            "script-dir/jquery-3.6.0.min.js",
    +            "script-dir/jquery-3.6.1.min.js",
                 "script-dir/jquery-ui.min.js",
                 "script-dir/jquery-ui.min.css",
                 "search.html",
    diff --git a/test/langtools/jdk/javadoc/tool/exceptionHandling/TestExceptionHandling.java b/test/langtools/jdk/javadoc/tool/exceptionHandling/TestExceptionHandling.java
    index a721b92841b..f51608eade1 100644
    --- a/test/langtools/jdk/javadoc/tool/exceptionHandling/TestExceptionHandling.java
    +++ b/test/langtools/jdk/javadoc/tool/exceptionHandling/TestExceptionHandling.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2016, 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
    @@ -60,7 +60,7 @@ public class TestExceptionHandling extends TestRunner {
         final JavadocTask apiTask;
     
         public static void main(String... args) throws Exception {
    -        TestExceptionHandling tester = new TestExceptionHandling();
    +        var tester = new TestExceptionHandling();
             tester.runTests();
         }
     
    diff --git a/test/langtools/jdk/javadoc/tool/removeOldDoclet/RemoveOldDoclet.java b/test/langtools/jdk/javadoc/tool/removeOldDoclet/RemoveOldDoclet.java
    index e9b92e9e557..e39394f8a4d 100644
    --- a/test/langtools/jdk/javadoc/tool/removeOldDoclet/RemoveOldDoclet.java
    +++ b/test/langtools/jdk/javadoc/tool/removeOldDoclet/RemoveOldDoclet.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2019, 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
    @@ -46,8 +46,8 @@ public class RemoveOldDoclet extends JavadocTester {
         static final String Doclet_CLASS_NAME = TestDoclet.class.getName();
     
         public static void main(String... args) throws Exception {
    -        RemoveOldDoclet tester = new RemoveOldDoclet();
    -        tester.runTests(m -> new Object[]{Paths.get(m.getName())});
    +        var tester = new RemoveOldDoclet();
    +        tester.runTests();
         }
     
         RemoveOldDoclet() {
    diff --git a/test/langtools/jdk/javadoc/tool/reporter_generates_warnings/ReporterGeneratesWarningsInsteadOfNotes.java b/test/langtools/jdk/javadoc/tool/reporter_generates_warnings/ReporterGeneratesWarningsInsteadOfNotes.java
    index fd7ade7585b..3667fb6c46b 100644
    --- a/test/langtools/jdk/javadoc/tool/reporter_generates_warnings/ReporterGeneratesWarningsInsteadOfNotes.java
    +++ b/test/langtools/jdk/javadoc/tool/reporter_generates_warnings/ReporterGeneratesWarningsInsteadOfNotes.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2019, 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
    @@ -103,7 +103,7 @@ public class ReporterGeneratesWarningsInsteadOfNotes extends TestRunner {
         }
     
         public static void main(String... args) throws Exception {
    -        ReporterGeneratesWarningsInsteadOfNotes tester = new ReporterGeneratesWarningsInsteadOfNotes();
    +        var tester = new ReporterGeneratesWarningsInsteadOfNotes();
             tester.runTests();
         }
     
    diff --git a/test/langtools/jdk/javadoc/tool/testToolStreams/TestToolStreams.java b/test/langtools/jdk/javadoc/tool/testToolStreams/TestToolStreams.java
    index 1140e2b7ac9..7ebfeff6773 100644
    --- a/test/langtools/jdk/javadoc/tool/testToolStreams/TestToolStreams.java
    +++ b/test/langtools/jdk/javadoc/tool/testToolStreams/TestToolStreams.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2021, 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
    @@ -41,8 +41,8 @@
     public class TestToolStreams extends JavadocTester {
     
         public static void main(String... args) throws Exception {
    -        TestToolStreams tester = new TestToolStreams();
    -        tester.runTests(m -> new Object[]{Path.of(m.getName())});
    +        var tester = new TestToolStreams();
    +        tester.runTests();
         }
     
         ToolBox tb = new ToolBox();
    diff --git a/test/langtools/jdk/javadoc/tool/testWErrorOption/TestWErrorOption.java b/test/langtools/jdk/javadoc/tool/testWErrorOption/TestWErrorOption.java
    index ee4761766b4..b403a3f5bcf 100644
    --- a/test/langtools/jdk/javadoc/tool/testWErrorOption/TestWErrorOption.java
    +++ b/test/langtools/jdk/javadoc/tool/testWErrorOption/TestWErrorOption.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2020, 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
    @@ -41,8 +41,8 @@
     public class TestWErrorOption extends JavadocTester {
     
         public static void main(String... args) throws Exception {
    -        TestWErrorOption tester = new TestWErrorOption();
    -        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
    +        var tester = new TestWErrorOption();
    +        tester.runTests();
         }
     
         private final ToolBox tb = new ToolBox();
    diff --git a/test/langtools/jdk/jshell/CompletionSuggestionTest.java b/test/langtools/jdk/jshell/CompletionSuggestionTest.java
    index 84662349c02..dda5e9f9f06 100644
    --- a/test/langtools/jdk/jshell/CompletionSuggestionTest.java
    +++ b/test/langtools/jdk/jshell/CompletionSuggestionTest.java
    @@ -23,7 +23,7 @@
     
     /*
      * @test
    - * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 8240658 8278039 8286206
    + * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 8240658 8278039 8286206 8296789
      * @summary Test Completion and Documentation
      * @library /tools/lib
      * @modules jdk.compiler/com.sun.tools.javac.api
    @@ -791,4 +791,10 @@ public void testStatements() {
         public void testRecord() {
             assertCompletion("record R() implements Ru|", true, "Runnable");
         }
    +
    +    //JDK-8296789
    +    public void testParentMembers() {
    +        assertEval("var sb=new StringBuilder();");
    +        assertCompletionIncludesExcludes("sb.|", true, Set.of("capacity()", "setLength("), Set.of("maybeLatin1"));
    +    }
     }
    diff --git a/test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java b/test/langtools/jdk/jshell/ConsoleTest.java
    similarity index 71%
    rename from test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java
    rename to test/langtools/jdk/jshell/ConsoleTest.java
    index b927ae76db6..5d2d8602df7 100644
    --- a/test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java
    +++ b/test/langtools/jdk/jshell/ConsoleTest.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 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
    @@ -23,19 +23,20 @@
     
     /*
      * @test
    - * @bug 8007475
    - * @summary Test memory stomp in stack map test
    - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest
    + * @bug 8298425
    + * @summary Verify behavior of System.console()
    + * @build KullaTesting TestingInputStream
    + * @run testng ConsoleTest
      */
    -public class StackMapFrameTest {
     
    -  public static void foo() {
    -    Object o = new Object();
    -  }
     
    -  public static void main(String args[]) {
    -    for (int i = 0; i < 25000; i++) {
    -      foo();
    +import org.testng.annotations.Test;
    +
    +public class ConsoleTest extends KullaTesting {
    +
    +    @Test
    +    public void testConsole1() {
    +        assertEval("System.console()", "null");
         }
    -  }
    +
     }
    diff --git a/test/langtools/jdk/jshell/Test8296012.java b/test/langtools/jdk/jshell/Test8296012.java
    index 8aa7b2e0ef7..923d7fb400f 100644
    --- a/test/langtools/jdk/jshell/Test8296012.java
    +++ b/test/langtools/jdk/jshell/Test8296012.java
    @@ -25,6 +25,7 @@
      * @test
      * @bug 8296012
      * @summary jshell crashes on mismatched record pattern
    + * @requires vm.continuations
      * @build KullaTesting TestingInputStream
      * @run testng Test8296012
      */
    @@ -44,4 +45,4 @@ public void test() {
         public void setUp() {
             super.setUp(bc -> bc.compilerOptions("--source", System.getProperty("java.specification.version"), "--enable-preview").remoteVMOptions("--enable-preview"));
         }
    -}
    \ No newline at end of file
    +}
    diff --git a/test/langtools/jdk/jshell/ToolFormatTest.java b/test/langtools/jdk/jshell/ToolFormatTest.java
    index 84ed32e91bd..3aaf5e79ea5 100644
    --- a/test/langtools/jdk/jshell/ToolFormatTest.java
    +++ b/test/langtools/jdk/jshell/ToolFormatTest.java
    @@ -23,7 +23,7 @@
     
     /*
      * @test
    - * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840 8166637 8161969 8173007
    + * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840 8166637 8161969 8173007 8299829
      * @summary Tests for output customization
      * @library /tools/lib
      * @modules jdk.compiler/com.sun.tools.javac.api
    @@ -300,7 +300,8 @@ public void testSetTruncation() {
                         (a) -> assertCommand(a, "/var", "|    String s = \"ABACABADA"),
                         (a) -> assertCommand(a, "String r = s", "String:\"ABACABAD ... BAXYZ\""),
                         (a) -> assertCommand(a, "r", "String:\"ABACABADA"),
    -                    (a) -> assertCommand(a, "r=s", "String:\"AB")
    +                    (a) -> assertCommand(a, "r=s", "String:\"AB"),
    +                    (a) -> assertCommand(a, "\"0\".repeat(49999)+\"2\"", "String:\"00000000 ... 00002\"")
                 );
             } finally {
                 assertCommandCheckOutput(false, "/set feedback normal", s -> {
    diff --git a/test/langtools/tools/doclint/BadPackageCommentTest.out b/test/langtools/tools/doclint/BadPackageCommentTest.out
    index 11153088426..136792f5852 100644
    --- a/test/langtools/tools/doclint/BadPackageCommentTest.out
    +++ b/test/langtools/tools/doclint/BadPackageCommentTest.out
    @@ -1,13 +1,13 @@
     BadPackageCommentTest.java:14: warning: documentation comment not expected here
     package p;
     ^
    -BadPackageCommentTest.java:12: error: no tag name after @
    +BadPackageCommentTest.java:12: error: no tag name after '@'
      * @@@
        ^
    -BadPackageCommentTest.java:12: error: no tag name after @
    +BadPackageCommentTest.java:12: error: no tag name after '@'
      * @@@
         ^
    -BadPackageCommentTest.java:12: error: no tag name after @
    +BadPackageCommentTest.java:12: error: no tag name after '@'
      * @@@
          ^
     3 errors
    diff --git a/test/langtools/tools/javac/Diagnostics/8043251/T8043251.java b/test/langtools/tools/javac/Diagnostics/8043251/T8043251.java
    new file mode 100644
    index 00000000000..dcf3586a507
    --- /dev/null
    +++ b/test/langtools/tools/javac/Diagnostics/8043251/T8043251.java
    @@ -0,0 +1,10 @@
    +/**
    + * @test /nodynamiccopyright/
    + * @bug     8043251
    + * @summary Confusing error message with wrong number of type parameters
    + * @compile/fail/ref=T8043251.out -XDrawDiagnostics T8043251.java
    + */
    +import java.util.function.Function;
    +class T8043251 {
    +    Function f = Function.identity();
    +}
    diff --git a/test/langtools/tools/javac/Diagnostics/8043251/T8043251.out b/test/langtools/tools/javac/Diagnostics/8043251/T8043251.out
    new file mode 100644
    index 00000000000..2b17605d7de
    --- /dev/null
    +++ b/test/langtools/tools/javac/Diagnostics/8043251/T8043251.out
    @@ -0,0 +1,2 @@
    +T8043251.java:9:42: compiler.err.cant.apply.symbol.noargs: kindname.method, identity, kindname.interface, java.util.function.Function, (compiler.misc.wrong.number.type.args: 1)
    +1 error
    diff --git a/test/langtools/tools/javac/T8297602.java b/test/langtools/tools/javac/T8297602.java
    new file mode 100644
    index 00000000000..5d7519d0318
    --- /dev/null
    +++ b/test/langtools/tools/javac/T8297602.java
    @@ -0,0 +1,52 @@
    +/*
    + * Copyright (c) 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 8297602
    + * @summary Compiler crash with type annotation and generic record during pattern matching
    + * @enablePreview
    + * @compile --enable-preview -source ${jdk.version} -XDrawDiagnostics T8297602.java
    + */
    +import java.lang.annotation.ElementType;
    +import java.lang.annotation.Target;
    +
    +public class T8297602
    +{
    +    void meth(Foo p) {
    +        switch(p) {
    +            case Foo<@Annot(field = "") Integer>(): {}
    +        };
    +
    +        if (p instanceof Foo<@Annot(field = "") Integer>()) {
    +
    +        }
    +    }
    +
    +    @Target({ElementType.TYPE_USE})
    +    @interface Annot {
    +        String field();
    +    }
    +
    +    record Foo() { }
    +}
    diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java
    index 207fdc8f913..b9b1e88d746 100644
    --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java
    +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java
    @@ -209,27 +209,27 @@ public void runDeconstruction() throws Exception {
                                   descriptor: ()V
                                   flags: (0x0001) ACC_PUBLIC
                                     RuntimeInvisibleTypeAnnotations:
    -                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=251, length=11, index=2}
    +                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=316, length=11, index=2}
                                         Patterns$DeconstructionPattern$A
    -                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=290, length=11, index=3}
    +                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=359, length=11, index=3}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    -                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=1}
    +                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=30, length=11, index=1}
                                         Patterns$DeconstructionPattern$A
    -                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=63, length=11, index=1}
    +                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=1}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    -                                  4: #_A_(): LOCAL_VARIABLE, {start_pc=101, length=11, index=2}
    +                                  4: #_A_(): LOCAL_VARIABLE, {start_pc=114, length=11, index=2}
                                         Patterns$DeconstructionPattern$A
    -                                  5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=140, length=11, index=3}
    +                                  5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=157, length=11, index=3}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    -                                  6: #_A_(): LOCAL_VARIABLE, {start_pc=176, length=11, index=2}
    +                                  6: #_A_(): LOCAL_VARIABLE, {start_pc=215, length=11, index=2}
                                         Patterns$DeconstructionPattern$A
    -                                  7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=215, length=11, index=3}
    +                                  7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=258, length=11, index=3}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    @@ -238,30 +238,26 @@ public void runDeconstruction() throws Exception {
                                   descriptor: ()V
                                   flags: (0x0000)
                                     RuntimeInvisibleTypeAnnotations:
    -                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=23, length=11, index=2}
    +                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=2}
                                         Patterns$DeconstructionPattern$A
    -                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=3}
    +                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=3}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
     
    -                            private static java.lang.String $proxy$s(Patterns$DeconstructionPattern$R);
    -                              descriptor: (LPatterns$DeconstructionPattern$R;)Ljava/lang/String;
    -                              flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    -
                                 static {};
                                   descriptor: ()V
                                   flags: (0x0008) ACC_STATIC
                                     RuntimeInvisibleTypeAnnotations:
    -                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=0}
    +                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=0}
                                         Patterns$DeconstructionPattern$A
    -                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=0}
    +                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=66, length=11, index=0}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    -                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=98, length=11, index=1}
    +                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=106, length=11, index=1}
                                         Patterns$DeconstructionPattern$A
    -                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=134, length=11, index=2}
    +                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=147, length=11, index=2}
                                         Patterns$DeconstructionPattern$CA(
                                           value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
                                         )
    diff --git a/test/langtools/tools/javac/api/TestGetSourceVersions.java b/test/langtools/tools/javac/api/TestGetSourceVersions.java
    index befdcac7d7a..168e76f330f 100644
    --- a/test/langtools/tools/javac/api/TestGetSourceVersions.java
    +++ b/test/langtools/tools/javac/api/TestGetSourceVersions.java
    @@ -35,7 +35,7 @@
      * @run main TestGetSourceVersions      RELEASE_3  RELEASE_4  RELEASE_5  RELEASE_6  RELEASE_7
      *                                      RELEASE_8  RELEASE_9  RELEASE_10 RELEASE_11 RELEASE_12
      *                                      RELEASE_13 RELEASE_14 RELEASE_15 RELEASE_16 RELEASE_17
    - *                                      RELEASE_18 RELEASE_19 RELEASE_20
    + *                                      RELEASE_18 RELEASE_19 RELEASE_20 RELEASE_21
      */
     
     import java.util.EnumSet;
    diff --git a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java
    index fad440c0880..d54b8da4e3f 100644
    --- a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java
    +++ b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java
    @@ -54,7 +54,8 @@ private static enum Version {
             SEVENTEEN("17", 61),
             EIGHTEEN("18", 62),
             NINETEEN("19", 63),
    -        TWENTY("20", 64);
    +        TWENTY("20", 64),
    +        TWENTY_ONE("21", 65);
     
             private Version(String release, int classFileVer) {
                 this.release = release;
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod b/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod
    new file mode 100644
    index 00000000000..88ac846ea54
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod
    @@ -0,0 +1,76 @@
    +//
    +//  class BadFieldFlags {
    +//      protected int my_field;
    +//  }
    +//
    +class BadFieldFlags {
    +  0xCAFEBABE;
    +  0; // minor version
    +  63; // version
    +  [] { // Constant Pool
    +    ; // first element is empty
    +    Method #2 #3; // #1
    +    class #4; // #2
    +    NameAndType #5 #6; // #3
    +    Utf8 "java/lang/Object"; // #4
    +    Utf8 ""; // #5
    +    Utf8 "()V"; // #6
    +    class #8; // #7
    +    Utf8 "BadFieldFlags"; // #8
    +    Utf8 "my_field"; // #9
    +    Utf8 "I"; // #10
    +    Utf8 "Code"; // #11
    +    Utf8 "LineNumberTable"; // #12
    +    Utf8 "SourceFile"; // #13
    +    Utf8 "BadFieldFlags.java"; // #14
    +  } // Constant Pool
    +
    +  0x0020; // access
    +  #7;// this_cpx
    +  #2;// super_cpx
    +
    +  [] { // Interfaces
    +  } // Interfaces
    +
    +  [] { // Fields
    +    {  // field
    +      0x0006; // access *** SHOULD BE 0x0004 ***
    +      #9; // name_index
    +      #10; // descriptor_index
    +      [] { // Attributes
    +      } // Attributes
    +    }
    +  } // Fields
    +
    +  [] { // Methods
    +    {  // method
    +      0x0000; // access
    +      #5; // name_index
    +      #6; // descriptor_index
    +      [] { // Attributes
    +        Attr(#11) { // Code
    +          1; // max_stack
    +          1; // max_locals
    +          Bytes[]{
    +            0x2AB70001B1;
    +          }
    +          [] { // Traps
    +          } // end Traps
    +          [] { // Attributes
    +            Attr(#12) { // LineNumberTable
    +              [] { // line_number_table
    +                0  1;
    +              }
    +            } // end LineNumberTable
    +          } // Attributes
    +        } // end Code
    +      } // Attributes
    +    }
    +  } // Methods
    +
    +  [] { // Attributes
    +    Attr(#13) { // SourceFile
    +      #14;
    +    } // end SourceFile
    +  } // Attributes
    +} // end class BadFieldFlags
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java
    new file mode 100644
    index 00000000000..947ec2f0637
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java
    @@ -0,0 +1,12 @@
    +/*
    + * @test /nodynamiccopyright/
    + * @bug 8219810
    + * @summary Verify ClassReader detects invalid field access flags combinations
    + * @build BadFieldFlags
    + * @compile/fail/ref=BadFieldFlagsTest.out -XDrawDiagnostics BadFieldFlagsTest.java
    + */
    +public class BadFieldFlagsTest {
    +    {
    +        System.out.println(new BadFieldFlags().my_field);
    +    }
    +}
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out
    new file mode 100644
    index 00000000000..f4c95cc9292
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out
    @@ -0,0 +1,2 @@
    +BadFieldFlagsTest.java:10:32: compiler.err.cant.access: BadFieldFlags, (compiler.misc.bad.class.file.header: BadFieldFlags.class, (compiler.misc.illegal.flag.combo: private protected, field, my_field))
    +1 error
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod b/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod
    new file mode 100644
    index 00000000000..dd391479a9b
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod
    @@ -0,0 +1,77 @@
    +//
    +//  class BadMethodFlags {
    +//      protected native int my_method();
    +//  }
    +//
    +class BadMethodFlags {
    +  0xCAFEBABE;
    +  0; // minor version
    +  63; // version
    +  [] { // Constant Pool
    +    ; // first element is empty
    +    Method #2 #3; // #1
    +    class #4; // #2
    +    NameAndType #5 #6; // #3
    +    Utf8 "java/lang/Object"; // #4
    +    Utf8 ""; // #5
    +    Utf8 "()V"; // #6
    +    class #8; // #7
    +    Utf8 "BadMethodFlags"; // #8
    +    Utf8 "Code"; // #9
    +    Utf8 "LineNumberTable"; // #10
    +    Utf8 "my_method"; // #11
    +    Utf8 "()I"; // #12
    +    Utf8 "SourceFile"; // #13
    +    Utf8 "BadMethodFlags.java"; // #14
    +  } // Constant Pool
    +
    +  0x0020; // access
    +  #7;// this_cpx
    +  #2;// super_cpx
    +
    +  [] { // Interfaces
    +  } // Interfaces
    +
    +  [] { // Fields
    +  } // Fields
    +
    +  [] { // Methods
    +    {  // method
    +      0x0000; // access
    +      #5; // name_index
    +      #6; // descriptor_index
    +      [] { // Attributes
    +        Attr(#9) { // Code
    +          1; // max_stack
    +          1; // max_locals
    +          Bytes[]{
    +            0x2AB70001B1;
    +          }
    +          [] { // Traps
    +          } // end Traps
    +          [] { // Attributes
    +            Attr(#10) { // LineNumberTable
    +              [] { // line_number_table
    +                0  1;
    +              }
    +            } // end LineNumberTable
    +          } // Attributes
    +        } // end Code
    +      } // Attributes
    +    }
    +    ;
    +    {  // method
    +      0x0105; // access *** SHOULD BE 0x0104 ***
    +      #11; // name_index
    +      #12; // descriptor_index
    +      [] { // Attributes
    +      } // Attributes
    +    }
    +  } // Methods
    +
    +  [] { // Attributes
    +    Attr(#13) { // SourceFile
    +      #14;
    +    } // end SourceFile
    +  } // Attributes
    +} // end class BadMethodFlags
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java
    new file mode 100644
    index 00000000000..579b48c0a4d
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java
    @@ -0,0 +1,12 @@
    +/*
    + * @test /nodynamiccopyright/
    + * @bug 8219810
    + * @summary Verify ClassReader detects invalid method access flags combinations
    + * @build BadMethodFlags
    + * @compile/fail/ref=BadMethodFlagsTest.out -XDrawDiagnostics BadMethodFlagsTest.java
    + */
    +public class BadMethodFlagsTest {
    +    {
    +        new BadMethodFlags().my_method();
    +    }
    +}
    diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out
    new file mode 100644
    index 00000000000..85f3d43341c
    --- /dev/null
    +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out
    @@ -0,0 +1,2 @@
    +BadMethodFlagsTest.java:10:13: compiler.err.cant.access: BadMethodFlags, (compiler.misc.bad.class.file.header: BadMethodFlags.class, (compiler.misc.illegal.flag.combo: public protected native, method, my_method()))
    +1 error
    diff --git a/test/langtools/tools/javac/diags/CheckResourceKeys.java b/test/langtools/tools/javac/diags/CheckResourceKeys.java
    index 1a0dcdba114..4b2d198113b 100644
    --- a/test/langtools/tools/javac/diags/CheckResourceKeys.java
    +++ b/test/langtools/tools/javac/diags/CheckResourceKeys.java
    @@ -32,6 +32,7 @@
     
     import java.io.*;
     import java.util.*;
    +import java.util.regex.*;
     import javax.tools.*;
     import com.sun.tools.classfile.*;
     import com.sun.tools.javac.code.Lint.LintCategory;
    @@ -47,6 +48,8 @@ public class CheckResourceKeys {
          *      look for keys in resource bundles that are no longer required
          * -findmissingkeys
          *      look for keys in resource bundles that are missing
    +     * -checkformats
    +     *      validate MessageFormat patterns in resource bundles
          *
          * @throws Exception if invoked by jtreg and errors occur
          */
    @@ -71,16 +74,19 @@ static boolean is_jtreg() {
         boolean run(String... args) throws Exception {
             boolean findDeadKeys = false;
             boolean findMissingKeys = false;
    +        boolean checkFormats = false;
     
             if (args.length == 0) {
                 if (is_jtreg()) {
                     findDeadKeys = true;
                     findMissingKeys = true;
    +                checkFormats = true;
                 } else {
                     System.err.println("Usage: java CheckResourceKeys ");
                     System.err.println("where options include");
                     System.err.println("  -finddeadkeys      find keys in resource bundles which are no longer required");
                     System.err.println("  -findmissingkeys   find keys in resource bundles that are required but missing");
    +                System.err.println("  -checkformats      validate MessageFormat patterns in resource bundles");
                     return true;
                 }
             } else {
    @@ -89,6 +95,8 @@ boolean run(String... args) throws Exception {
                         findDeadKeys = true;
                     else if (arg.equalsIgnoreCase("-findmissingkeys"))
                         findMissingKeys = true;
    +                else if (arg.equalsIgnoreCase("-checkformats"))
    +                    checkFormats = true;
                     else
                         error("bad option: " + arg);
                 }
    @@ -106,6 +114,9 @@ else if (arg.equalsIgnoreCase("-findmissingkeys"))
             if (findMissingKeys)
                 findMissingKeys(codeStrings, resourceKeys);
     
    +        if (checkFormats)
    +            checkFormats(getMessageFormatBundles());
    +
             return (errors == 0);
         }
     
    @@ -312,6 +323,109 @@ void findMissingKeys(Set codeStrings, Set resourceKeys) {
                 "locn."
         ));
     
    +    void checkFormats(List messageFormatBundles) {
    +        for (ResourceBundle bundle : messageFormatBundles) {
    +            for (String key : bundle.keySet()) {
    +                final String pattern = bundle.getString(key);
    +                try {
    +                    validateMessageFormatPattern(pattern);
    +                } catch (IllegalArgumentException e) {
    +                    error("Invalid MessageFormat pattern for resource \""
    +                        + key + "\": " + e.getMessage());
    +                }
    +            }
    +        }
    +    }
    +
    +    /**
    +     * Do some basic validation of a {@link java.text.MessageFormat} format string.
    +     *
    +     * 

    + * This checks for balanced braces and unnecessary quoting. + * Code cut, pasted, & simplified from {@link java.text.MessageFormat#applyPattern}. + * + * @throws IllegalArgumentException if {@code pattern} is invalid + * @throws IllegalArgumentException if {@code pattern} is null + */ + public static void validateMessageFormatPattern(String pattern) { + + // Check for null + if (pattern == null) + throw new IllegalArgumentException("null pattern"); + + // Replicate the quirky lexical analysis of MessageFormat's parsing algorithm + final int SEG_RAW = 0; + final int SEG_INDEX = 1; + final int SEG_TYPE = 2; + final int SEG_MODIFIER = 3; + int part = SEG_RAW; + int braceStack = 0; + int quotedStartPos = -1; + for (int i = 0; i < pattern.length(); i++) { + final char ch = pattern.charAt(i); + if (part == SEG_RAW) { + if (ch == '\'') { + if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') + i++; + else if (quotedStartPos == -1) + quotedStartPos = i; + else { + validateMessageFormatQuoted(pattern.substring(quotedStartPos + 1, i)); + quotedStartPos = -1; + } + } else if (ch == '{' && quotedStartPos == -1) + part = SEG_INDEX; + continue; + } + if (quotedStartPos != -1) { + if (ch == '\'') { + validateMessageFormatQuoted(pattern.substring(quotedStartPos + 1, i)); + quotedStartPos = -1; + } + continue; + } + switch (ch) { + case ',': + if (part < SEG_MODIFIER) + part++; + break; + case '{': + braceStack++; + break; + case '}': + if (braceStack == 0) + part = SEG_RAW; + else + braceStack--; + break; + case '\'': + quotedStartPos = i; + break; + default: + break; + } + } + if (part != SEG_RAW) + throw new IllegalArgumentException("unmatched braces"); + if (quotedStartPos != -1) + throw new IllegalArgumentException("unmatched quote starting at offset " + quotedStartPos); + } + + /** + * Validate the content of a quoted substring in a {@link java.text.MessageFormat} pattern. + * + *

    + * We expect this content to contain at least one special character. Otherwise, + * it was probably meant to be something in single quotes but somebody forgot + * to escape the single quotes by doulbing them; and even if intentional, + * it's still bogus because the single quotes are just going to get discarded + * and so they were unnecessary in the first place. + */ + static void validateMessageFormatQuoted(String quoted) { + if (quoted.matches("[^'{},]+")) + throw new IllegalArgumentException("unescaped single quotes around \"" + quoted + "\""); + } + /** * Look for a resource that ends in this string fragment. */ @@ -405,6 +519,20 @@ Set getResourceKeys() { return results; } + /** + * Get resource bundles containing MessageFormat strings. + */ + List getMessageFormatBundles() { + Module jdk_compiler = ModuleLayer.boot().findModule("jdk.compiler").get(); + List results = new ArrayList<>(); + for (String name : new String[]{"compiler", "launcher"}) { + ResourceBundle b = + ResourceBundle.getBundle("com.sun.tools.javac.resources." + name, jdk_compiler); + results.add(b); + } + return results; + } + /** * Report an error. */ diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index afceccad633..9d1c9a2f0af 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -66,6 +66,7 @@ compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower compiler.misc.fatal.err.cant.close # JavaCompiler compiler.misc.feature.not.supported.in.source.plural # cannot happen (for now) compiler.misc.file.does.not.contain.package +compiler.misc.illegal.flag.combo # ClassReader compiler.misc.illegal.start.of.class.file compiler.misc.inferred.do.not.conform.to.lower.bounds # cannot happen? compiler.misc.kindname.annotation diff --git a/test/langtools/tools/javac/diags/examples/ExplicitParamsDoNotConformToBounds.java b/test/langtools/tools/javac/diags/examples/ExplicitParamsDoNotConformToBounds.java index cd10b13180d..6f8047af3aa 100644 --- a/test/langtools/tools/javac/diags/examples/ExplicitParamsDoNotConformToBounds.java +++ b/test/langtools/tools/javac/diags/examples/ExplicitParamsDoNotConformToBounds.java @@ -21,7 +21,7 @@ * questions. */ -// key: compiler.err.cant.apply.symbol +// key: compiler.err.cant.apply.symbol.noargs // key: compiler.misc.explicit.param.do.not.conform.to.bounds class ExplicitParamsDoNotConformToBounds { diff --git a/test/langtools/tools/javac/diags/examples/WrongNumberTypeArgsFragment.java b/test/langtools/tools/javac/diags/examples/WrongNumberTypeArgsFragment.java index c1777bba20f..8b0cc90c694 100644 --- a/test/langtools/tools/javac/diags/examples/WrongNumberTypeArgsFragment.java +++ b/test/langtools/tools/javac/diags/examples/WrongNumberTypeArgsFragment.java @@ -21,7 +21,7 @@ * questions. */ -// key: compiler.err.cant.apply.symbol +// key: compiler.err.cant.apply.symbol.noargs // key: compiler.misc.wrong.number.type.args import java.util.*; diff --git a/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.java b/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.java deleted file mode 100644 index b920368bea8..00000000000 --- a/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @summary Verify for() loop variable not effectively final even if loop never increments - * @bug 8294461 - * @compile/fail/ref=EffectivelyFinalLoopIncrement.out -XDrawDiagnostics EffectivelyFinalLoopIncrement.java - */ -class EffectivelyFinalLoopIncrement { - EffectivelyFinalLoopIncrement() { - for (int i = 0; i < 10; i++) { - Runnable r = () -> System.out.println(i); // variable i is NOT effectively final - break; // even though "i++" is never reached - } - } -} diff --git a/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.out b/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.out deleted file mode 100644 index 8fbf3ab69b1..00000000000 --- a/test/langtools/tools/javac/lambda/8294461/EffectivelyFinalLoopIncrement.out +++ /dev/null @@ -1,2 +0,0 @@ -EffectivelyFinalLoopIncrement.java:10:51: compiler.err.cant.ref.non.effectively.final.var: i, (compiler.misc.lambda) -1 error diff --git a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java index b1afc5d7cbc..cba0bd23e1f 100644 --- a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java +++ b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java @@ -112,7 +112,7 @@ protected void addExports(String moduleName, String... packageNames) { * corresponding platform visitor type. */ - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractAnnotationValueVisitor extends AbstractAnnotationValueVisitor14 { /** @@ -123,7 +123,7 @@ protected AbstractAnnotationValueVisitor() { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractElementVisitor extends AbstractElementVisitor14 { /** * Constructor for concrete subclasses to call. @@ -133,7 +133,7 @@ protected AbstractElementVisitor(){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractTypeVisitor extends AbstractTypeVisitor14 { /** * Constructor for concrete subclasses to call. @@ -143,7 +143,7 @@ protected AbstractTypeVisitor() { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class ElementKindVisitor extends ElementKindVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -164,7 +164,7 @@ protected ElementKindVisitor(R defaultValue) { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class ElementScanner extends ElementScanner14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -183,7 +183,7 @@ protected ElementScanner(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleAnnotationValueVisitor extends SimpleAnnotationValueVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -204,7 +204,7 @@ protected SimpleAnnotationValueVisitor(R defaultValue) { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleElementVisitor extends SimpleElementVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -225,7 +225,7 @@ protected SimpleElementVisitor(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleTypeVisitor extends SimpleTypeVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -246,7 +246,7 @@ protected SimpleTypeVisitor(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class TypeKindVisitor extends TypeKindVisitor14 { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index 5d699b04b10..0262066d7b8 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311 8241519 + * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311 8241519 8297988 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules @@ -39,6 +39,7 @@ import java.io.BufferedWriter; import java.io.Writer; import java.nio.file.Files; +import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; @@ -65,10 +66,13 @@ import javax.tools.ToolProvider; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; //import com.sun.source.util.JavacTask; // conflicts with toolbox.JavacTask import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symtab; +import java.util.ArrayList; import toolbox.JarTask; import toolbox.JavacTask; @@ -1047,4 +1051,106 @@ public void testMisnamedModuleInfoClass(Path base) throws Exception { throw new Exception("expected output not found: " + log); } + @Test //JDK-8297988 + public void testExportedNameCheckFromSourceNoEvent(Path base) throws Exception { + //when validating "exports", javac may parse source(s) from the package to check their + //package name. The AST produced by this parse are thrown away, so listeners should not + //be notified: + Path src = base.resolve("src"); + Path m = src.resolve("m"); + tb.writeJavaFiles(m, + """ + module m { + exports test; + } + """, + """ + package test; + public class Test {} + """, + """ + package impl; + public class Impl { + void t() { + test.Test t; + } + } + """); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + record TestCase(Path[] files, String... expectedLog){} + String nameSeparator = FileSystems.getDefault().getSeparator(); + + TestCase[] testCases = new TestCase[] { + new TestCase(new Path[] {m.resolve("module-info.java")}, + "COMPILATION:started:", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "COMPILATION:finished:"), + new TestCase(new Path[] {m.resolve("module-info.java"), + m.resolve("impl").resolve("Impl.java")}, + "COMPILATION:started:", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "COMPILATION:finished:") + }; + + for (TestCase tc : testCases) { + List log = new ArrayList<>(); + + new JavacTask(tb) + .outdir(classes) + .options("--source-path", m.toString(), + "-XDshould-stop.ifNoError=FLOW") + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void started(TaskEvent e) { + record(e, "started"); + } + @Override + public void finished(TaskEvent e) { + record(e, "finished"); + } + private void record(TaskEvent e, String phase) { + JavaFileObject source = e.getSourceFile(); + String sourceName = source != null ? source.getName() + .replace(nameSeparator, "/") + : ""; + log.add(e.getKind() + ":" + phase + ":" + sourceName); + } + }); + }) + .files(tc.files) + .run() + .writeAll(); + + if (!List.of(tc.expectedLog).equals(log)) { + throw new AssertionError("Unexpected log, got: " + log + + ", expected: " + List.of(tc.expectedLog)); + } + } + } + } diff --git a/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java b/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java new file mode 100644 index 00000000000..47b988b6284 --- /dev/null +++ b/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 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 8291769 + * @summary Verify more complex switches work properly + * @compile --enable-preview -source ${jdk.version} DeconstructionDesugaring.java + * @run main/othervm --enable-preview DeconstructionDesugaring + */ + +import java.util.function.ToIntFunction; +public class DeconstructionDesugaring { + + public static void main(String... args) throws Throwable { + new DeconstructionDesugaring().test(); + } + + private void test() { + test(this::runCheckStatement); + test(this::runCheckExpression); + assertEquals(runCheckExpressionWithUnconditional(new R5(new R4(new Sub3()))), 3); + assertEquals(runCheckExpressionWithUnconditional(new R5(new R4(null))), 3); + assertEquals(runCheckExpressionWithUnconditional1(new R5(new R4(null))), 2); + assertEquals(runCheckExpressionWithUnconditional1(new R5(null)), 3); + } + + private void test(ToIntFunction task) { + assertEquals(1, task.applyAsInt(new R1(new R2("")))); + assertEquals(2, task.applyAsInt(new R1(new R2(1)))); + assertEquals(3, task.applyAsInt(new R1(new R2(1.0)))); + assertEquals(-1, task.applyAsInt(new R1(new R2(null)))); + assertEquals(4, task.applyAsInt(new R1(new R2(new StringBuilder())))); + assertEquals(5, task.applyAsInt(new R1(new R3("")))); + assertEquals(6, task.applyAsInt(new R1(new R3(1)))); + assertEquals(7, task.applyAsInt(new R1(new R3(1.0)))); + assertEquals(8, task.applyAsInt(new R1(new R3(new StringBuilder())))); + assertEquals(-1, task.applyAsInt(new R1(1.0f))); + assertEquals(-1, task.applyAsInt("foo")); + } + + private int runCheckStatement(Object o) { + switch (o) { + case (((R1((((R2((((String s))))))))))) -> { return 1; } + case R1(R2(Integer i)) -> { return 2; } + case R1(R2(Double d)) -> { return 3; } + case R1(R2(CharSequence cs)) -> { return 4; } + case R1(R3(String s)) -> { return 5; } + case R1(R3(Integer i)) -> { return 6; } + case R1(R3(Double f)) -> { return 7; } + case R1(R3(CharSequence cs)) -> { return 8; } + default -> { return -1; } + } + } + + private int runCheckExpression(Object o) { + return switch (o) { + case (((R1((((R2((((String s))))))))))) -> 1; + case R1(R2(Integer i)) -> 2; + case R1(R2(Double d)) -> 3; + case R1(R2(CharSequence cs)) -> 4; + case R1(R3(String s)) -> 5; + case R1(R3(Integer i)) -> 6; + case R1(R3(Double f)) -> 7; + case R1(R3(CharSequence cs)) -> 8; + default -> -1; + }; + } + + private int runCheckExpressionWithUnconditional(R5 o) { + return switch (o) { + case R5(R4(Sub1 s)) -> 1; + case R5(R4(Sub2 s)) -> 2; + case R5(R4(Super s)) -> 3; + }; + } + + private int runCheckExpressionWithUnconditional1(R5 o) { + return switch (o) { + case R5(R4(Sub1 s)) -> 1; + case R5(R4(Super s)) -> 2; + case R5(Object obj) -> 3; + }; + } + + private void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new AssertionError("expected: " + expected + ", " + + "actual: " + actual); + } + } + + record R1(Object o) {} + record R2(Object o) {} + record R3(Object o) {} + + sealed class Super permits Sub1, Sub2, Sub3 {} + final class Sub1 extends Super {} + final class Sub2 extends Super {} + final class Sub3 extends Super {} + + record R4(Super o) {} + record R5(R4 o) {} +} diff --git a/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java b/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java index 9b9a7dcccba..fa59657970e 100644 --- a/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java +++ b/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java @@ -23,7 +23,10 @@ /** * @test + * @bug 8298184 * @enablePreview + * @compile GenericRecordDeconstructionPattern.java + * @run main GenericRecordDeconstructionPattern */ import java.util.List; import java.util.Objects; @@ -46,6 +49,8 @@ void run() { testInference3(); assertEquals(0, forEachInference(List.of(new Box("")))); assertEquals(1, forEachInference(List.of(new Box(null)))); + assertEquals(1, runIfSuperBound(new Box<>(new StringBuilder()))); + assertEquals(1, runIfSuperBound(new Box<>(0))); } void runTest(Function, Integer> test) { @@ -120,6 +125,11 @@ int runSwitchInferenceNested(I> b) { } } + int runIfSuperBound(I b) { + if (b instanceof Box(var v)) return 1; + return -1; + } + sealed interface I {} record Box(V v) implements I { } diff --git a/test/langtools/tools/javac/patterns/Guards.java b/test/langtools/tools/javac/patterns/Guards.java index f8cffd41655..3292bdc9fb0 100644 --- a/test/langtools/tools/javac/patterns/Guards.java +++ b/test/langtools/tools/javac/patterns/Guards.java @@ -55,6 +55,7 @@ void run(Function convert) { assertEquals("one", convert.apply(1)); assertEquals("other", convert.apply(-1)); assertEquals("box with empty", convert.apply(new Box(""))); + assertEquals("box with non-empty", convert.apply(new Box("a"))); assertEquals("any", convert.apply("")); } @@ -70,6 +71,7 @@ String typeTestPatternSwitchTest(Object o) { case Integer i when i == 1: return "one"; case Integer i: return "other"; case Box(String s) when s.isEmpty(): return "box with empty"; + case Box(String s) : return "box with non-empty"; case Object x: return "any"; } } @@ -80,6 +82,7 @@ String typeTestPatternSwitchExpressionTest(Object o) { case Integer i when i == 1 -> { yield "one"; } case Integer i -> "other"; case Box(String s) when s.isEmpty() -> "box with empty"; + case Box(String s) -> "box with non-empty"; case Object x -> "any"; }; } @@ -91,6 +94,7 @@ String testBooleanSwitchExpression(Object o) { case Integer i when i == 1 -> { x = "one"; yield true; } case Integer i -> { x = "other"; yield true; } case Box(String s) when s.isEmpty() -> {x = "box with empty"; yield true; } + case Box(String s) -> {x = "box with non-empty"; yield true; } case Object other -> (x = "any") != null; }) { return x; diff --git a/test/langtools/tools/javac/patterns/PatternDesugaring.java b/test/langtools/tools/javac/patterns/PatternDesugaring.java new file mode 100644 index 00000000000..67c19b2441b --- /dev/null +++ b/test/langtools/tools/javac/patterns/PatternDesugaring.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 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 8291769 + * @summary Verify the compiled code does not have unwanted constructs. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavacTask + * @run main PatternDesugaring +*/ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.function.Consumer; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.JavapTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class PatternDesugaring extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new PatternDesugaring().runTests(); + } + + PatternDesugaring() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testPrimitiveNoBoxUnbox(Path base) throws Exception { + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return switch (obj) { + case R(int i) -> i; + default -> -1; + }; + } + record R(int i) {} + } + """, + decompiled -> { + if (decompiled.contains("intValue") || decompiled.contains("valueOf")) { + throw new AssertionError("Has boxing/unboxing."); + } + }); + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return obj instanceof R(int i) ? i : -1; + } + record R(int i) {} + } + """, + decompiled -> { + if (decompiled.contains("intValue") || decompiled.contains("valueOf")) { + throw new AssertionError("Has boxing/unboxing."); + } + }); + } + + @Test + public void testCacheRecordsForRecordPatterns(Path base) throws Exception { + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return switch (obj) { + case R(Integer i, Integer j, Integer k) -> i + j + k; + default -> -1; + }; + } + record R(Integer i, Integer j, Integer k) {} + } + """, + decompiled -> { + if (decompiled.split("checkcast").length != 2) { + throw new AssertionError("Unexpected number of checkcasts."); + } + }); + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return obj instanceof R(Integer i, Integer j, Integer k) ? i + j + k: -1; + } + record R(Integer i, Integer j, Integer k) {} + } + """, + decompiled -> { + if (decompiled.split("checkcast").length != 2) { + throw new AssertionError("Unexpected number of checkcasts."); + } + }); + } + + private void doTest(Path base, String[] libraryCode, String testCode, Consumer validate) throws IOException { + Path current = base.resolve("."); + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + if (libraryCode.length != 0) { + Path libSrc = current.resolve("lib-src"); + + for (String code : libraryCode) { + tb.writeJavaFiles(libSrc, code); + } + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + } + + Path src = current.resolve("src"); + tb.writeJavaFiles(src, testCode); + + Path classes = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString(), + "-XDshould-stop.at=FLOW") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + var decompiled = + new JavapTask(tb) + .classpath(classes.toString()) + .classes("test.Test") + .options("-s", "-verbose") + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + System.err.println("decompiled: " + decompiled); + + validate.accept(decompiled); + } + +} diff --git a/test/langtools/tools/javac/patterns/Switches.java b/test/langtools/tools/javac/patterns/Switches.java index 48eda83e8cb..1c7ae41274e 100644 --- a/test/langtools/tools/javac/patterns/Switches.java +++ b/test/langtools/tools/javac/patterns/Switches.java @@ -92,6 +92,10 @@ void run() { assertEquals("a", deconstructExpression(new R("a"))); assertEquals("1", deconstructExpression(new R(1))); assertEquals("other", deconstructExpression("")); + assertEquals("a", translationTest("a")); + assertEquals("Rb", translationTest(new R("b"))); + assertEquals("R2c", translationTest(new R2("c"))); + assertEquals("other", translationTest(0)); assertEquals("OK", totalPatternAndNull(Integer.valueOf(42))); assertEquals("OK", totalPatternAndNull(null)); assertEquals("1", nullAfterTotal(Integer.valueOf(42))); @@ -99,6 +103,8 @@ void run() { emptyFallThrough(1); emptyFallThrough(""); emptyFallThrough(1.0); + testSimpleSwitch(); + testSimpleSwitchExpression(); } void run(Function mapper) { @@ -636,6 +642,15 @@ String deconstructExpression(Object o) { }; } + String translationTest(Object o) { + return switch (o) { + case R(String s) -> "R" + s; + case String s -> s; + case R2(String s) -> "R2" + s; + default -> "other"; + }; + } + String totalPatternAndNull(Integer in) { return switch (in) { case -1: { yield "";} @@ -659,6 +674,23 @@ void emptyFallThrough(Object o) { } } + void testSimpleSwitch() { + Object o = ""; + int res; + switch (o) { + default -> res = 1; + }; + assertEquals(1, res); + } + + void testSimpleSwitchExpression() { + Object o = ""; + int res = switch (o) { + default -> 1; + }; + assertEquals(1, res); + } + //verify that for cases like: //case ConstantClassClash -> //ConstantClassClash is interpreted as a field, not as a class @@ -700,4 +732,5 @@ public enum E implements Runnable { } record R(Object o) {} + record R2(Object o) {} } diff --git a/test/langtools/tools/javac/patterns/TranslationTest.java b/test/langtools/tools/javac/patterns/TranslationTest.java new file mode 100644 index 00000000000..f77b04fc9a3 --- /dev/null +++ b/test/langtools/tools/javac/patterns/TranslationTest.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 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 8291769 + * @summary Check expected translation of various pattern related constructs + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main TranslationTest +*/ + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.TransPatterns; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCase; +import com.sun.tools.javac.tree.JCTree.JCSwitch; +import com.sun.tools.javac.tree.JCTree.JCSwitchExpression; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class TranslationTest extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new TranslationTest().runTests(); + } + + TranslationTest() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testSimple(Path base) throws Exception { + doTest(base, + new String[]{""" + package lib; + public record Box(Object o) {} + """}, + """ + package test; + import lib.*; + public class Test { + private int test(Object obj) { + return switch (obj) { + case Box(String s) -> 0; + case Box(Integer i) -> 0; + case Box(Number n) -> 0; + case Box(CharSequence cs) -> 0; + + default -> -1; + }; + } + } + """, + toplevel -> printSwitchStructure(toplevel), + """ + switch + case + switch + case + case + case + case + case ..., default + default + """); + } + + @Test + public void testMultiComponent(Path base) throws Exception { + doTest(base, + new String[]{""" + package lib; + public record Pair(Object o1, Object o2) {} + """, + """ + package lib; + public record Triplet(Object o1, Object o2, Object o3) {} + """}, + """ + package test; + import lib.*; + public class Test { + private int test(Object obj) { + return switch (obj) { + case Pair(String c1, Pair(String o2, String s2)) -> 0; + case Pair(String c1, Pair(String o2, Integer s2)) -> 0; + case Pair(String c1, Pair(Integer o2, String s2)) -> 0; + case Pair(String c1, Pair(Integer o2, Integer s2)) -> 0; + + case Pair(Integer c1, Pair(String o2, String s2)) -> 0; + case Pair(Integer c1, Pair(String o2, Integer s2)) -> 0; + case Pair(Integer c1, Pair(Integer o2, String s2)) -> 0; + case Pair(Integer c1, Pair(Integer o2, Integer s2)) -> 0; + + default -> -1; + }; + } + } + """, + toplevel -> printSwitchStructure(toplevel), + """ + switch + case + switch + case + switch + case + switch + case + switch + case + case + case ..., default + case + switch + case + case + case ..., default + case ..., default + case ..., default + case + switch + case + switch + case + switch + case + case + case ..., default + case + switch + case + case + case ..., default + case ..., default + case ..., default + case ..., default + default + """); + } + + private void doTest(Path base, String[] libraryCode, String testCode, + Callback callback, String expectedOutput) throws IOException { + Path current = base.resolve("."); + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + if (libraryCode.length != 0) { + Path libSrc = current.resolve("lib-src"); + + for (String code : libraryCode) { + tb.writeJavaFiles(libSrc, code); + } + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + } + + Path src = current.resolve("src"); + tb.writeJavaFiles(src, testCode); + + Path classes = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + List output = new ArrayList<>(); + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-Xlint:-preview", + "--class-path", libClasses.toString(), + "-XDshould-stop.at=FLOW") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .callback(task -> { + Context ctx = ((JavacTaskImpl) task).getContext(); + + TestTransPatterns.preRegister(ctx, callback, output); + }) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + if (output.size() != 1 || !expectedOutput.equals(output.get(0))) { + throw new AssertionError("Unexpected output:\n" + output); + } + } + + private String printSwitchStructure(JCTree topLevel) { + StringBuilder structure = new StringBuilder(); + + new TreeScanner() { + private static final int INDENT = 4; + private int indent = 0; + @Override + public void visitSwitch(JCSwitch node) { + int prevIndent = indent; + appendLine("switch"); + try { + indent += INDENT; + super.visitSwitch(node); + } finally { + indent = prevIndent; + } + } + + @Override + public void visitSwitchExpression(JCSwitchExpression node) { + int prevIndent = indent; + appendLine("switch"); + try { + indent += INDENT; + super.visitSwitchExpression(node); + } finally { + indent = prevIndent; + } + } + @Override + public void visitCase(JCCase node) { + int prevIndent = indent; + if (node.labels.size() == 1 && node.labels.head.hasTag(Tag.DEFAULTCASELABEL)) { + appendLine("default"); + } else if (node.labels.stream().anyMatch(l -> l.hasTag(Tag.DEFAULTCASELABEL))) { + appendLine("case ..., default"); + } else { + appendLine("case"); + } + try { + indent += INDENT; + super.visitCase(node); + } finally { + indent = prevIndent; + } + } + private void appendLine(String what) { + for (int i = 0; i < indent; i++) { + structure.append(' '); + } + structure.append(what); + structure.append('\n'); + } + }.scan(topLevel); + + return structure.toString(); + } + + public interface Callback { + public String patternsTranslated(JCTree topLevel); + } + + private static final class TestTransPatterns extends TransPatterns { + + public static void preRegister(Context ctx, Callback validator, List output) { + ctx.put(transPatternsKey, (Factory) c -> new TestTransPatterns(c, validator, output)); + } + + private final Callback callback; + private final List output; + + public TestTransPatterns(Context context, Callback callback, List output) { + super(context); + this.callback = callback; + this.output = output; + } + + @Override + public JCTree translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + JCTree result = super.translateTopLevelClass(env, cdef, make); + output.add(callback.patternsTranslated(cdef)); + return result; + } + + } +} diff --git a/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java b/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java index a93cfa61071..8dcae4e6f89 100644 --- a/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java +++ b/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java @@ -28,6 +28,7 @@ import java.util.Objects; import java.util.function.Function; +import java.util.function.ToIntFunction; public class TypedDeconstructionPatternExc { @@ -38,6 +39,9 @@ public static void main(String... args) throws Throwable { void run() { run(this::testExpr); run(this::testExprCond); + testTryExpr(); + run(this::testLambda); + runBoxed(); } void run(Function, Integer> tested) { @@ -82,6 +86,82 @@ int testExprCond(Pair p) { } } + void testTryExpr() { + TEST: { + try { + var v = switch ((Pair) (Object) new Pair(1, 1)) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } catch (ClassCastException ex) { + //OK + break TEST; + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected Throwable!"); + } + fail("ClassCastException not thrown!"); + } + TEST: { + try { + var v = switch (new Pair("fail", 1)) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } catch (MatchException ex) { + //OK + break TEST; + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected Throwable!"); + } + fail("MatchException not thrown!"); + } + } + + int testLambda(Pair p) { + var r = prepareLambda(); + return r.applyAsInt(p); + } + + ToIntFunction> prepareLambda() { + return p -> switch (p) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } + + void runBoxed() { + assertEquals(2, testBoxed(new Box(new Pair<>("1", 1)))); + try { + testBoxed(new Box((Pair) (Object) new Pair(1, 1))); + fail("Expected an exception, but none happened!"); + } catch (ClassCastException ex) { + System.err.println("expected exception:"); + ex.printStackTrace(); + } + try { + testBoxed(new Box(new Pair("fail", 1))); + fail("Expected an exception, but none happened!"); + } catch (MatchException ex) { + assertEquals(TestPatternFailed.class.getName() + ": " + EXCEPTION_MESSAGE, + ex.getMessage()); + if (ex.getCause() instanceof TestPatternFailed ex2) { + System.err.println("expected exception:"); + ex2.printStackTrace(); + } else { + fail("Not the correct exception."); + } + } + } + + int testBoxed(Object p) { + return switch (p) { + case Box(Pair(String s, Integer i)) -> s.length() + i; + case Object o -> -1; + }; + } + static final String EXCEPTION_MESSAGE = "exception-message"; record Pair(L l, R r) { @@ -96,6 +176,8 @@ public R r() { } } + record Box(Pair boxed) {} + void assertEquals(Object expected, Object actual) { if (!Objects.equals(expected, actual)) { throw new AssertionError("Expected: " + expected + "," + diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out index 8e8e88b4bcc..d6e16a69307 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out @@ -1,2 +1,2 @@ -- compiler.err.preview.feature.disabled.classfile: Bar.class, 20 +- compiler.err.preview.feature.disabled.classfile: Bar.class, 21 1 error diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out index af28e2f1cf0..d05eeb0ebee 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out @@ -1,4 +1,4 @@ -- compiler.warn.preview.feature.use.classfile: Bar.class, 20 +- compiler.warn.preview.feature.use.classfile: Bar.class, 21 - compiler.err.warnings.and.werror 1 error 1 warning diff --git a/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java new file mode 100644 index 00000000000..4acf1e3abac --- /dev/null +++ b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 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 8298727 + * @summary Verify empty package-info.java is handled properly + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.TestRunner toolbox.ToolBox EmptyPackageInfo + * @run main EmptyPackageInfo + */ + +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import com.sun.source.util.Trees; +import java.util.ArrayList; +import java.util.List; +import javax.tools.ToolProvider; +import toolbox.TestRunner; +import toolbox.TestRunner.Test; +import toolbox.ToolBox; + +public class EmptyPackageInfo extends TestRunner { + + public static void main(String... args) throws Exception { + new EmptyPackageInfo().runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + private final ToolBox tb = new ToolBox(); + + public EmptyPackageInfo() { + super(System.err); + } + + @Test + public void testEmptyPackageInfo(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo = src.resolve("package-info.java"); + + tb.writeFile(packInfo, "/**javadoc*/\n"); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var task = + (JavacTask) compiler.getTask(null, + fm, + null, + null, + null, + fm.getJavaFileObjects(packInfo)); + task.analyze(); + var pack = task.getElements().getPackageElement(""); + var trees = Trees.instance(task); + var packPath = trees.getPath(pack); + var packTree = packPath.getLeaf(); + if (packTree.getKind() != Tree.Kind.COMPILATION_UNIT) { + throw new AssertionError("Unexpected tree kind: " + packTree.getKind()); + } + var actualJavadoc = trees.getDocComment(packPath); + var expectedJavadoc = "javadoc"; + if (!expectedJavadoc.equals(actualJavadoc)) { + throw new AssertionError("Unexpected javadoc, " + + "expected: " + expectedJavadoc + + ", got: " + actualJavadoc); + } + } + } + + @Test + public void testMultipleFiles(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo1 = src.resolve("test1").resolve("package-info.java"); + Path packInfo2 = src.resolve("test2").resolve("package-info.java"); + + tb.writeFile(packInfo1, ""); + tb.writeFile(packInfo2, ""); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var diags = new ArrayList(); + var task = + (JavacTask) compiler.getTask(null, + fm, + d -> diags.add(d.getCode()), + null, + null, + fm.getJavaFileObjects(packInfo1, + packInfo2)); + task.analyze(); + var expectedDiags = + List.of("compiler.warn.pkg-info.already.seen"); + if (!expectedDiags.equals(diags)) { + throw new AssertionError("Unexpected diags, " + + "expected: " + expectedDiags + + ", got: " + diags); + } + } + } +} diff --git a/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java b/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java new file mode 100644 index 00000000000..ae611e3d511 --- /dev/null +++ b/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 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 8295184 + * @summary Printing messages with a RecordComponentElement does not include position + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @compile TestWarning.java + * @compile ReproducingAP.java + * @run main RecordComponentSourcePositionTest + */ + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import toolbox.JavacTask; +import toolbox.TestRunner; +import toolbox.ToolBox; +import toolbox.Task; + +public class RecordComponentSourcePositionTest extends TestRunner { + + ToolBox tb; + + public RecordComponentSourcePositionTest() { + super(System.err); + tb = new ToolBox(); + } + + public static void main(String[] args) throws Exception { + RecordComponentSourcePositionTest t = new RecordComponentSourcePositionTest(); + t.runTests(); + } + + @Test + public void testRecordComponentPositionInDiagnostics() throws Exception { + String code = """ + @TestWarning(includeAnnotation = true) + public record Test( + @TestWarning(includeAnnotation = true) int first, + @TestWarning int second) { + } + + @TestWarning + record Test2() {} + """; + + Path curPath = Path.of("."); + + List output = new JavacTask(tb) + .sources(code) + .outdir(curPath) + .options("-XDrawDiagnostics", "-processor", "ReproducingAP") + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "Test.java:1:1: compiler.warn.proc.messager: Reporting Test with an annotation", + "Test.java:3:9: compiler.warn.proc.messager: Reporting first with an annotation", + "Test.java:4:26: compiler.warn.proc.messager: Reporting second", + "Test.java:8:1: compiler.warn.proc.messager: Reporting Test2", + "4 warnings"); + tb.checkEqual(expected, output); + } +} diff --git a/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java b/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java new file mode 100644 index 00000000000..c9de1fdafd3 --- /dev/null +++ b/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 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. + */ + +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; + +public class ReproducingAP extends AbstractProcessor { + + @Override + public Set getSupportedAnnotationTypes() { + return Set.of(TestWarning.class.getName()); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + roundEnv.getElementsAnnotatedWith(TestWarning.class).forEach(e -> { + var annotation = e.getAnnotation(TestWarning.class); + if (annotation.includeAnnotation()) { + processingEnv.getMessager().printMessage( + javax.tools.Diagnostic.Kind.WARNING, + "Reporting " + e.getSimpleName() + " with an annotation", + e, + e.getAnnotationMirrors().get(0)); + } else { + processingEnv.getMessager().printMessage( + javax.tools.Diagnostic.Kind.WARNING, + "Reporting " + e.getSimpleName(), + e); + } + }); + return false; + } +} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java b/test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java similarity index 69% rename from test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java rename to test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java index 0b76901b4f5..942e6c1ad10 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java +++ b/test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -21,14 +21,16 @@ * questions. */ -package org.reactivestreams; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; /** - * A Processor represents a processing stage—which is both a {@link Subscriber} - * and a {@link Publisher} and obeys the contracts of both. - * - * @param the type of element signaled to the {@link Subscriber} - * @param the type of element signaled by the {@link Publisher} + * Direct {@link ReproducingAP} to emit a warning. */ -public interface Processor extends Subscriber, Publisher { +@Target({ElementType.TYPE, ElementType.RECORD_COMPONENT}) +public @interface TestWarning { + /** + * {@return {@code true} to include the relevant mirror in the warning message} + */ + boolean includeAnnotation() default false; } diff --git a/test/langtools/tools/javac/recovery/LambdaRecovery.java b/test/langtools/tools/javac/recovery/LambdaRecovery.java new file mode 100644 index 00000000000..74d796d0b02 --- /dev/null +++ b/test/langtools/tools/javac/recovery/LambdaRecovery.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 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 8297974 + * @summary Verify error recovery w.r.t. lambdas + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.classfile + * @build toolbox.ToolBox toolbox.JavacTask + * @run main LambdaRecovery + */ + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +import toolbox.JavacTask; +import toolbox.Task.Expect; +import toolbox.Task.OutputKind; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class LambdaRecovery extends TestRunner { + + ToolBox tb; + + public LambdaRecovery() { + super(System.err); + tb = new ToolBox(); + } + + public static void main(String[] args) throws Exception { + LambdaRecovery t = new LambdaRecovery(); + t.runTests(); + } + + @Test + public void testRecoveryExpressionLambda() throws Exception { + String code = """ + class Test { + interface I { + int convert(int i); + } + interface O { + Object convert(Object o); + } + void t1(I f, String e) { + t1(param -> param); + t1(param -> voidMethod(param)); + } + void t2(O f, String e) { + t2(param -> param); + t2(param -> voidMethod(param)); + } + void voidMethod(Object o) {} + } + """; + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code) + .outdir(curPath) + .run(Expect.FAIL) + .getOutputLines(OutputKind.DIRECT); + + List expected = List.of( + "Test.java:9:9: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:10:9: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:10:11: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12,, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: void, int)))", + "Test.java:13:9: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:14:9: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:14:11: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12,, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: void, java.lang.Object)))", + "6 errors" + ); + + if (!Objects.equals(actual, expected)) { + error("Expected: " + expected + ", but got: " + actual); + } + + } +} diff --git a/test/langtools/tools/javac/scope/DupUnsharedTest.java b/test/langtools/tools/javac/scope/DupUnsharedTest.java index 55d23cf38e2..ed65bc719f8 100644 --- a/test/langtools/tools/javac/scope/DupUnsharedTest.java +++ b/test/langtools/tools/javac/scope/DupUnsharedTest.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8064362 * @summary WriteableScope.dupUnshared not working properly for shared Scopes. * @modules jdk.compiler/com.sun.tools.javac.code:+open * jdk.compiler/com.sun.tools.javac.file diff --git a/test/langtools/tools/javac/versions/Versions.java b/test/langtools/tools/javac/versions/Versions.java index 99fe34c9424..1a7f618b9f2 100644 --- a/test/langtools/tools/javac/versions/Versions.java +++ b/test/langtools/tools/javac/versions/Versions.java @@ -71,24 +71,25 @@ public static void main(String... args) throws IOException { public static final Set VALID_SOURCES = Set.of("1.8", "1.9", "1.10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20"); + "15", "16", "17", "18", "19", "20", "21"); - public static final String LATEST_MAJOR_VERSION = "64.0"; + public static final String LATEST_MAJOR_VERSION = "65.0"; static enum SourceTarget { - EIGHT(true, "52.0", "8", Versions::checksrc8), - NINE(true, "53.0", "9", Versions::checksrc9), - TEN(true, "54.0", "10", Versions::checksrc10), - ELEVEN(false, "55.0", "11", Versions::checksrc11), - TWELVE(false, "56.0", "12", Versions::checksrc12), - THIRTEEN(false, "57.0", "13", Versions::checksrc13), - FOURTEEN(false, "58.0", "14", Versions::checksrc14), - FIFTEEN(false, "59.0", "15", Versions::checksrc15), - SIXTEEN(false, "60.0", "16", Versions::checksrc16), + EIGHT(true, "52.0", "8", Versions::checksrc8), + NINE(true, "53.0", "9", Versions::checksrc9), + TEN(true, "54.0", "10", Versions::checksrc10), + ELEVEN(false, "55.0", "11", Versions::checksrc11), + TWELVE(false, "56.0", "12", Versions::checksrc12), + THIRTEEN(false, "57.0", "13", Versions::checksrc13), + FOURTEEN(false, "58.0", "14", Versions::checksrc14), + FIFTEEN(false, "59.0", "15", Versions::checksrc15), + SIXTEEN(false, "60.0", "16", Versions::checksrc16), SEVENTEEN(false, "61.0", "17", Versions::checksrc17), EIGHTEEN(false, "62.0", "18", Versions::checksrc18), NINETEEN(false, "63.0", "19", Versions::checksrc19), - TWENTY(false, "64.0", "20", Versions::checksrc20); + TWENTY(false, "64.0", "20", Versions::checksrc20), + TWENTY_ONE(false,"65.0", "21", Versions::checksrc20); private final boolean dotOne; private final String classFileVer; diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT index cbda44ae379..306d2bd7c6e 100644 --- a/test/lib-test/TEST.ROOT +++ b/test/lib-test/TEST.ROOT @@ -29,7 +29,7 @@ keys=randomness # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 784f018435e..647c62834aa 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -293,6 +293,10 @@ public static boolean isHardenedOSX() throws IOException { isHardened = true; System.out.println("Target JDK is hardened. Some tests may be skipped."); } else if (line.indexOf("flags=0x20002(adhoc,linker-signed)") != -1 ) { + hardenedStatusConfirmed = true; + isHardened = false; + System.out.println("Target JDK is adhoc linker-signed, but not hardened."); + } else if (line.indexOf("flags=0x2(adhoc)") != -1 ) { hardenedStatusConfirmed = true; isHardened = false; System.out.println("Target JDK is adhoc signed, but not hardened."); diff --git a/test/lib/jdk/test/lib/SecurityTools.java b/test/lib/jdk/test/lib/SecurityTools.java index 6e3a55f7e5c..ff13343ad32 100644 --- a/test/lib/jdk/test/lib/SecurityTools.java +++ b/test/lib/jdk/test/lib/SecurityTools.java @@ -40,8 +40,7 @@ /** * Run security tools (including jarsigner and keytool) in a new process. * The en_US locale is always used so a test can always match output to - * English text. {@code /dev/urandom} is used as entropy source so tool will - * not block because of entropy scarcity. An argument can be a normal string, + * English text. An argument can be a normal string, * {@code -Jvm-options}, or {@code $sysProp}. */ public class SecurityTools { @@ -58,9 +57,6 @@ public static ProcessBuilder getProcessBuilder(String tool, List args) { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(tool) .addVMArg("-Duser.language=en") .addVMArg("-Duser.country=US"); - if (!Platform.isWindows()) { - launcher.addVMArg("-Djava.security.egd=file:/dev/./urandom"); - } for (String arg : args) { if (arg.startsWith("-J")) { launcher.addVMArg(arg.substring(2)); diff --git a/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java b/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java index f3c2179191f..c06f5d7b70f 100644 --- a/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java +++ b/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package jdk.test.lib.artifacts; /** diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java index 168f5bb29c6..a6eff3d237a 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2020, 2022, 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 @@ -52,14 +52,22 @@ private static CgroupMetricsTester createInstance(Metrics m) { } } - public void testAll(Metrics m) throws Exception { + private void testAll(Metrics m, boolean inContainer) throws Exception { CgroupMetricsTester tester = createInstance(m); tester.testCpuAccounting(); tester.testCpuConsumption(); tester.testCpuSchedulingMetrics(); tester.testCpuSets(); - tester.testMemorySubsystem(); - tester.testMemoryUsage(); + if (!inContainer) { + // If not running in a container, these test cases query the memory usage. + // of all processes in the entire system (or those belonging to the current + // Linux user). They cannot produce predictable results due to interference + // from unrelated processes. + System.out.println("testMemorySubsystem and testMemoryUsage skipped"); + } else { + tester.testMemorySubsystem(); + tester.testMemoryUsage(); + } tester.testMisc(); } @@ -71,8 +79,14 @@ public static void main(String[] args) throws Exception { return; } + boolean inContainer = false; + if (args.length > 0 && "-incontainer".equals(args[0])) { + inContainer = true; + } + System.out.println("inContainer = " + inContainer); + MetricsTester metricsTester = new MetricsTester(); - metricsTester.testAll(m); + metricsTester.testAll(m, inContainer); System.out.println("TEST PASSED!!!"); } } diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java index 5a0a03766fd..87e526f3c73 100644 --- a/test/lib/jdk/test/lib/jfr/EventNames.java +++ b/test/lib/jdk/test/lib/jfr/EventNames.java @@ -86,6 +86,8 @@ public class EventNames { public static final String RetransformClasses = PREFIX + "RetransformClasses"; public static final String ClassRedefinition = PREFIX + "ClassRedefinition"; public static final String FinalizerStatistics = PREFIX + "FinalizerStatistics"; + public static final String NativeMemoryUsage = PREFIX + "NativeMemoryUsage"; + public static final String NativeMemoryUsageTotal = PREFIX + "NativeMemoryUsageTotal"; // This event is hard to test public static final String ReservedStackActivation = PREFIX + "ReservedStackActivation"; diff --git a/test/lib/jdk/test/lib/jfr/GCHelper.java b/test/lib/jdk/test/lib/jfr/GCHelper.java index 699c272905e..316a4767e25 100644 --- a/test/lib/jdk/test/lib/jfr/GCHelper.java +++ b/test/lib/jdk/test/lib/jfr/GCHelper.java @@ -175,6 +175,7 @@ public static List removeFirstAndLastGC(List event // old GarbageCollectionMXBeans. beanCollectorTypes.put("G1 Old Generation", false); + beanCollectorTypes.put("G1 Concurrent GC", false); beanCollectorTypes.put("PS MarkSweep", false); beanCollectorTypes.put("MarkSweepCompact", false); diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index c787cb19c40..33be681c97c 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -358,8 +358,12 @@ public static ProcessBuilder createJavaProcessBuilder(String... command) { ArrayList args = new ArrayList<>(); args.add(javapath); - args.add("-cp"); - args.add(System.getProperty("java.class.path")); + String noCPString = System.getProperty("test.noclasspath", "false"); + boolean noCP = Boolean.valueOf(noCPString); + if (!noCP) { + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + } String mainWrapper = System.getProperty("main.wrapper"); if (mainWrapper != null) { @@ -374,7 +378,12 @@ public static ProcessBuilder createJavaProcessBuilder(String... command) { cmdLine.append(cmd).append(' '); System.out.println("Command line: [" + cmdLine.toString() + "]"); - return new ProcessBuilder(args); + ProcessBuilder pb = new ProcessBuilder(args); + if (noCP) { + // clear CLASSPATH from the env + pb.environment().remove("CLASSPATH"); + } + return pb; } private static void printStack(Thread t, StackTraceElement[] stack) { diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index dbe5d065fc4..a6cf27a79ba 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -165,7 +165,52 @@ public void addToSystemClassLoaderSearch(String segment) { } // G1 + public native boolean g1InConcurrentMark(); + public native int g1CompletedConcurrentMarkCycles(); + + // Perform a complete concurrent GC cycle, using concurrent GC breakpoints. + // Completes any in-progress cycle before performing the requested cycle. + // Returns true if the cycle completed successfully. If the cycle was not + // successful (e.g. it was aborted), then throws RuntimeException if + // errorIfFail is true, returning false otherwise. + public boolean g1RunConcurrentGC(boolean errorIfFail) { + try { + // Take control, waiting until any in-progress cycle completes. + concurrentGCAcquireControl(); + int count = g1CompletedConcurrentMarkCycles(); + concurrentGCRunTo(AFTER_MARKING_STARTED, false); + concurrentGCRunToIdle(); + if (count < g1CompletedConcurrentMarkCycles()) { + return true; + } else if (errorIfFail) { + throw new RuntimeException("Concurrent GC aborted"); + } else { + return false; + } + } finally { + concurrentGCReleaseControl(); + } + } + + public void g1RunConcurrentGC() { + g1RunConcurrentGC(true); + } + + // Start a concurrent GC cycle, using concurrent GC breakpoints. + // The concurrent GC will continue in parallel with the caller. + // Completes any in-progress cycle before starting the requested cycle. + public void g1StartConcurrentGC() { + try { + // Take control, waiting until any in-progress cycle completes. + concurrentGCAcquireControl(); + concurrentGCRunTo(AFTER_MARKING_STARTED, false); + } finally { + // Release control, permitting the cycle to complete. + concurrentGCReleaseControl(); + } + } + public native boolean g1HasRegionsToUncommit(); private native boolean g1IsHumongous0(Object o); public boolean g1IsHumongous(Object o) { @@ -540,10 +585,6 @@ public boolean concurrentGCRunTo(String breakpoint, boolean errorIfFail) { } } - // Method tries to start concurrent mark cycle. - // It returns false if CM Thread is always in concurrent cycle. - public native boolean g1StartConcMarkCycle(); - // Tests on ReservedSpace/VirtualSpace classes public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations); public native void readFromNoaccessArea(); diff --git a/test/micro/org/openjdk/bench/java/io/RandomAccessFileBenchmark.java b/test/micro/org/openjdk/bench/java/io/RandomAccessFileBenchmark.java new file mode 100644 index 00000000000..68738a42b59 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/RandomAccessFileBenchmark.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 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 micro.org.openjdk.bench.java.io; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.*; +import java.nio.file.Files; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@Fork(2) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Measurement(iterations = 5, time = 2) + +public class RandomAccessFileBenchmark { + + @Param({"1", "5"}) + private int kiloBytes; + private int size; + private File file; + + private RandomAccessFile raf; + + private short[] shorts; + private int[] ints; + private long[] longs; + + @Setup(Level.Iteration) + public void beforeRun() throws IOException { + Random rnd = ThreadLocalRandom.current(); + size = kiloBytes << 10; + var bytes = new byte[size]; + rnd.nextBytes(bytes); + file = File.createTempFile(getClass().getName(), ".txt"); + Files.write(file.toPath(), bytes); + shorts = new short[size]; + for (int i = 0; i < size / Short.BYTES; i++) { + shorts[i] = (short) rnd.nextInt(); + } + ints = rnd.ints(size / Integer.BYTES).toArray(); + longs = rnd.longs(size / Long.BYTES).toArray(); + raf = new RandomAccessFile(file, "rw"); + // Make it more likely file content is directly available + for (int i = 0; i < size / Integer.BYTES; i++) { + raf.readInt(); + } + } + + @TearDown(Level.Iteration) + public void afterRun() throws IOException { + raf.close(); + file.delete(); + } + + @Benchmark + public void readShort(Blackhole bh) throws IOException { + raf.seek(0); + for (int i = 0; i < size / Short.BYTES; i++) { + bh.consume(raf.readShort()); + } + } + + @Benchmark + public void readInt(Blackhole bh) throws IOException { + raf.seek(0); + for (int i = 0; i < size / Integer.BYTES; i++) { + bh.consume(raf.readInt()); + } + } + + @Benchmark + public void readLong(Blackhole bh) throws IOException { + raf.seek(0); + for (int i = 0; i < size / Long.BYTES; i++) { + bh.consume(raf.readLong()); + } + } + + @Benchmark + public void writeShort() throws IOException { + raf.seek(0); + for (int i = 0; i < size / Short.BYTES; i++) { + raf.writeShort(shorts[i]); + } + } + + @Benchmark + public void writeInt() throws IOException { + raf.seek(0); + for (int i = 0; i < size / Integer.BYTES; i++) { + raf.writeInt(ints[i]); + } + } + + @Benchmark + public void writeLong() throws IOException { + raf.seek(0); + for (int i = 0; i < size / Long.BYTES; i++) { + raf.writeLong(longs[i]); + } + } + +} diff --git a/test/micro/org/openjdk/bench/java/lang/ArrayFiddle.java b/test/micro/org/openjdk/bench/java/lang/ArrayFiddle.java index bade9493dc3..b95fc2788c6 100644 --- a/test/micro/org/openjdk/bench/java/lang/ArrayFiddle.java +++ b/test/micro/org/openjdk/bench/java/lang/ArrayFiddle.java @@ -45,7 +45,7 @@ * simple_copyLoop is surprisingly 5x slower. The array copying intrinsics * are very effective and a naive loop does not get optimized the same way. * OTOH there is no intrinsic for Arrays.fill but the naive array zeroing loop - * *does* get optimized to something a little faster than than arraycopy. + * *does* get optimized to something a little faster than arraycopy. * * System.arraycopy and Arrays.fill have such outstanding performance that * one should use them to replace handwritten loops whenever possible. diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java index a8fb7d9fc37..61b705e5b26 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java @@ -37,8 +37,8 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -52,18 +52,17 @@ public class BulkMismatchAcquire { public enum SessionKind { - CONFINED(MemorySession::openConfined), - SHARED(MemorySession::openShared), - IMPLICIT(MemorySession::openImplicit); + CONFINED(Arena::openConfined), + SHARED(Arena::openShared); - final Supplier sessionFactory; + final Supplier arenaFactory; - SessionKind(Supplier sessionFactory) { - this.sessionFactory = sessionFactory; + SessionKind(Supplier arenaFactory) { + this.arenaFactory = arenaFactory; } - MemorySession makeSession() { - return sessionFactory.get(); + Arena makeArena() { + return arenaFactory.get(); } } @@ -73,7 +72,7 @@ MemorySession makeSession() { // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; - MemorySession session; + Arena arena; MemorySegment mismatchSegmentLarge1; MemorySegment mismatchSegmentLarge2; ByteBuffer mismatchBufferLarge1; @@ -85,15 +84,15 @@ MemorySession makeSession() { @Setup public void setup() { - session = sessionKind.makeSession(); - mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); - mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); + arena = sessionKind.makeArena(); + mismatchSegmentLarge1 = arena.allocate(SIZE_WITH_TAIL); + mismatchSegmentLarge2 = arena.allocate(SIZE_WITH_TAIL); mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); // mismatch at first byte - mismatchSegmentSmall1 = MemorySegment.allocateNative(7, session); - mismatchSegmentSmall2 = MemorySegment.allocateNative(7, session); + mismatchSegmentSmall1 = arena.allocate(7); + mismatchSegmentSmall2 = arena.allocate(7); mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); { @@ -117,9 +116,7 @@ public void setup() { @TearDown public void tearDown() { - if (session.isCloseable()) { - session.close(); - } + arena.close(); } @Benchmark @@ -132,7 +129,7 @@ public long mismatch_large_segment() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_large_segment_acquire() { long[] arr = new long[1]; - mismatchSegmentLarge1.session().whileAlive(() -> { + mismatchSegmentLarge1.scope().whileAlive(() -> { arr[0] = mismatchSegmentLarge1.mismatch(mismatchSegmentSmall2); }); return arr[0]; @@ -154,7 +151,7 @@ public long mismatch_small_segment() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_small_segment_acquire() { long[] arr = new long[1]; - mismatchSegmentLarge1.session().whileAlive(() -> { + mismatchSegmentLarge1.scope().whileAlive(() -> { arr[0] = mismatchSegmentSmall1.mismatch(mismatchSegmentSmall2); }); return arr[0]; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java index cfb11d937e5..64ad5c4b377 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java @@ -37,14 +37,15 @@ import org.openjdk.jmh.annotations.Warmup; import sun.misc.Unsafe; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -60,10 +61,10 @@ public class BulkOps { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - final MemorySession session = MemorySession.openConfined(); + final Arena arena = Arena.openShared(); final long unsafe_addr = unsafe.allocateMemory(ALLOC_SIZE); - final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); final IntBuffer buffer = IntBuffer.allocate(ELEM_SIZE); final int[] ints = new int[ELEM_SIZE]; @@ -72,14 +73,14 @@ public class BulkOps { // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; - final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); - final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); + final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, arena.scope()); + final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, arena.scope());; final ByteBuffer mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); final ByteBuffer mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); // mismatch at first byte - final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, session); - final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, session); + final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, arena.scope());; + final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, arena.scope());; final ByteBuffer mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); final ByteBuffer mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); @@ -108,7 +109,7 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark @@ -138,20 +139,20 @@ public void segment_copy() { @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, ints.length); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, ints.length); } @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_small() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, 10); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, 10); } @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_small_dontinline() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, 10); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, 10); } @Benchmark @@ -176,7 +177,7 @@ public void buffer_copy() { @CompilerControl(CompilerControl.Mode.DONT_INLINE) @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_dontinline() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, ints.length); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, ints.length); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java index 24cc10047d3..d88838905fd 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java @@ -23,10 +23,9 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -67,17 +66,17 @@ public class CLayouts { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS; + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.asUnbounded(); private static Linker LINKER = Linker.nativeLinker(); private static final MethodHandle FREE = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); + LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); private static final MethodHandle MALLOC = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS.asUnbounded(), ValueLayout.JAVA_LONG)); - public static void freeMemory(Addressable address) { + public static void freeMemory(MemorySegment address) { try { FREE.invokeExact(address); } catch (Throwable ex) { @@ -85,9 +84,9 @@ public static void freeMemory(Addressable address) { } } - public static MemoryAddress allocateMemory(long size) { + public static MemorySegment allocateMemory(long size) { try { - return (MemoryAddress)MALLOC.invokeExact(size); + return (MemorySegment)MALLOC.invokeExact(size); } catch (Throwable ex) { throw new IllegalStateException(ex); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java index d87c48b56f5..e542276ccf6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java @@ -22,8 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -87,53 +85,38 @@ public MemorySegment panama_identity_struct_shared_3() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_shared() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(confinedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(sharedPoint, sharedPoint, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(confinedPoint, confinedPoint, confinedPoint); } @Benchmark - public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint); + public MemorySegment panama_identity_memory_address_null() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(MemorySegment.NULL); } @Benchmark - public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint); + public MemorySegment panama_identity_memory_address_null_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); } @Benchmark - public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_memory_address_null() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)MemoryAddress.NULL); - } - - @Benchmark - public MemoryAddress panama_identity_memory_address_null_non_exact() throws Throwable { - return (MemoryAddress) identity_memory_address.invoke(MemoryAddress.NULL); + public MemorySegment panama_identity_memory_address_null_non_exact() throws Throwable { + return (MemorySegment) identity_memory_address.invoke(MemorySegment.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java index 32ff0ffdee1..bbbc0afbb0f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java @@ -22,12 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.SymbolLookup; @@ -42,51 +42,51 @@ public class CallOverheadHelper extends CLayouts { static final MethodHandle func; static final MethodHandle func_v; - static Addressable func_addr; + static MemorySegment func_addr; static final MethodHandle identity; static final MethodHandle identity_v; - static Addressable identity_addr; + static MemorySegment identity_addr; static final MethodHandle identity_struct; static final MethodHandle identity_struct_v; - static Addressable identity_struct_addr; + static MemorySegment identity_struct_addr; static final MethodHandle identity_struct_3; static final MethodHandle identity_struct_3_v; - static Addressable identity_struct_3_addr; + static MemorySegment identity_struct_3_addr; static final MethodHandle identity_memory_address; static final MethodHandle identity_memory_address_v; - static Addressable identity_memory_address_addr; + static MemorySegment identity_memory_address_addr; static final MethodHandle identity_memory_address_3; static final MethodHandle identity_memory_address_3_v; - static Addressable identity_memory_address_3_addr; + static MemorySegment identity_memory_address_3_addr; static final MethodHandle args1; static final MethodHandle args1_v; - static Addressable args1_addr; + static MemorySegment args1_addr; static final MethodHandle args2; static final MethodHandle args2_v; - static Addressable args2_addr; + static MemorySegment args2_addr; static final MethodHandle args3; static final MethodHandle args3_v; - static Addressable args3_addr; + static MemorySegment args3_addr; static final MethodHandle args4; static final MethodHandle args4_v; - static Addressable args4_addr; + static MemorySegment args4_addr; static final MethodHandle args5; static final MethodHandle args5_v; - static Addressable args5_addr; + static MemorySegment args5_addr; static final MethodHandle args10; static final MethodHandle args10_v; - static Addressable args10_addr; + static MemorySegment args10_addr; static final MemoryLayout POINT_LAYOUT = MemoryLayout.structLayout( C_INT, C_INT ); - static final MemorySegment sharedPoint = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openShared()); - static final MemorySegment confinedPoint = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openConfined()); + static final MemorySegment sharedPoint = MemorySegment.allocateNative(POINT_LAYOUT, Arena.openShared().scope()); + static final MemorySegment confinedPoint = MemorySegment.allocateNative(POINT_LAYOUT, Arena.openConfined().scope()); - static final MemorySegment point = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openImplicit()); + static final MemorySegment point = MemorySegment.allocateNative(POINT_LAYOUT, SegmentScope.auto()); - static final SegmentAllocator recycling_allocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openImplicit())); + static final SegmentAllocator recycling_allocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(POINT_LAYOUT, SegmentScope.auto())); static { System.loadLibrary("CallOverheadJNI"); @@ -94,64 +94,64 @@ public class CallOverheadHelper extends CLayouts { System.loadLibrary("CallOverhead"); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); { - func_addr = loaderLibs.lookup("func").orElseThrow(); + func_addr = loaderLibs.find("func").orElseThrow(); MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); func_v = abi.downcallHandle(fd); func = insertArguments(func_v, 0, func_addr); } { - identity_addr = loaderLibs.lookup("identity").orElseThrow(); + identity_addr = loaderLibs.find("identity").orElseThrow(); FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT); identity_v = abi.downcallHandle(fd); identity = insertArguments(identity_v, 0, identity_addr); } - identity_struct_addr = loaderLibs.lookup("identity_struct").orElseThrow(); + identity_struct_addr = loaderLibs.find("identity_struct").orElseThrow(); identity_struct_v = abi.downcallHandle( FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT)); identity_struct = insertArguments(identity_struct_v, 0, identity_struct_addr); - identity_struct_3_addr = loaderLibs.lookup("identity_struct_3").orElseThrow(); + identity_struct_3_addr = loaderLibs.find("identity_struct_3").orElseThrow(); identity_struct_3_v = abi.downcallHandle( FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT)); identity_struct_3 = insertArguments(identity_struct_3_v, 0, identity_struct_3_addr); - identity_memory_address_addr = loaderLibs.lookup("identity_memory_address").orElseThrow(); + identity_memory_address_addr = loaderLibs.find("identity_memory_address").orElseThrow(); identity_memory_address_v = abi.downcallHandle( FunctionDescriptor.of(C_POINTER, C_POINTER)); identity_memory_address = insertArguments(identity_memory_address_v, 0, identity_memory_address_addr); - identity_memory_address_3_addr = loaderLibs.lookup("identity_memory_address_3").orElseThrow(); + identity_memory_address_3_addr = loaderLibs.find("identity_memory_address_3").orElseThrow(); identity_memory_address_3_v = abi.downcallHandle( FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER, C_POINTER)); identity_memory_address_3 = insertArguments(identity_memory_address_3_v, 0, identity_memory_address_3_addr); - args1_addr = loaderLibs.lookup("args1").orElseThrow(); + args1_addr = loaderLibs.find("args1").orElseThrow(); args1_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG)); args1 = insertArguments(args1_v, 0, args1_addr); - args2_addr = loaderLibs.lookup("args2").orElseThrow(); + args2_addr = loaderLibs.find("args2").orElseThrow(); args2_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE)); args2 = insertArguments(args2_v, 0, args2_addr); - args3_addr = loaderLibs.lookup("args3").orElseThrow(); + args3_addr = loaderLibs.find("args3").orElseThrow(); args3_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args3 = insertArguments(args3_v, 0, args3_addr); - args4_addr = loaderLibs.lookup("args4").orElseThrow(); + args4_addr = loaderLibs.find("args4").orElseThrow(); args4_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); args4 = insertArguments(args4_v, 0, args4_addr); - args5_addr = loaderLibs.lookup("args5").orElseThrow(); + args5_addr = loaderLibs.find("args5").orElseThrow(); args5_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args5 = insertArguments(args5_v, 0, args5_addr); - args10_addr = loaderLibs.lookup("args10").orElseThrow(); + args10_addr = loaderLibs.find("args10").orElseThrow(); args10_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java index 10fe5a9055b..de3b275e034 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java @@ -22,8 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -81,43 +79,23 @@ public MemorySegment panama_identity_struct_shared_3() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_shared() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, confinedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared_3() throws Throwable { + return (MemorySegment) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, sharedPoint, sharedPoint, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)confinedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); + public MemorySegment panama_identity_memory_address_confined_3() throws Throwable { + return (MemorySegment) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, confinedPoint, confinedPoint, confinedPoint); } @Benchmark @@ -131,8 +109,8 @@ public MemorySegment panama_identity_struct() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_null() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)MemoryAddress.NULL); + public MemorySegment panama_identity_memory_address_null() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, MemorySegment.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java index bc395a23105..56ebaad5410 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java @@ -26,29 +26,15 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.*; /** * Some useful Java {@link ValueLayout} and associated {@link ValueLayout#arrayElementVarHandle(int...)} var handles. */ public class JavaLayouts { - static final ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - - static final ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - - static final ValueLayout.OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8); static final VarHandle VH_INT_UNALIGNED = JAVA_INT_UNALIGNED.arrayElementVarHandle(); static final VarHandle VH_INT = JAVA_INT.arrayElementVarHandle(); - static final VarHandle VH_FLOAT_UNALIGNED = JAVA_FLOAT_UNALIGNED.arrayElementVarHandle(); - - static final VarHandle VH_FLOAT = JAVA_FLOAT.arrayElementVarHandle(); - - static final VarHandle VH_LONG_UNALIGNED = JAVA_LONG_UNALIGNED.arrayElementVarHandle(); - - static final VarHandle VH_LONG = JAVA_LONG.arrayElementVarHandle(); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java index 917370d2157..57b42a0e24a 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java @@ -35,7 +35,7 @@ import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.concurrent.TimeUnit; @@ -64,7 +64,7 @@ public class LinkUpcall extends CLayouts { @Benchmark public MemorySegment link_blank() { - return LINKER.upcallStub(BLANK, BLANK_DESC, MemorySession.openImplicit()); + return LINKER.upcallStub(BLANK, BLANK_DESC, SegmentScope.auto()); } static void blank() {} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java index ded0d8ca09f..a01891894f7 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java @@ -22,7 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.MemorySession; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -37,11 +36,12 @@ import sun.misc.Unsafe; import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -69,7 +69,7 @@ public class LoopOverConstant extends JavaLayouts { //setup native memory segment - static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openImplicit()); + static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, SegmentScope.auto()); static { for (int i = 0; i < ELEM_SIZE; i++) { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java index c1598522516..05be20222fa 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java @@ -22,10 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -42,7 +44,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -58,12 +60,12 @@ public class LoopOverNew extends JavaLayouts { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; static final MemoryLayout ALLOC_LAYOUT = MemoryLayout.sequenceLayout(ELEM_SIZE, JAVA_INT); - final MemorySession session = MemorySession.openConfined(); - final SegmentAllocator recyclingAlloc = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(ALLOC_LAYOUT, session)); + final Arena arena = Arena.openConfined(); + final SegmentAllocator recyclingAlloc = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(ALLOC_LAYOUT, arena.scope())); @TearDown public void tearDown() throws Throwable { - session.close(); + arena.close(); } @Benchmark @@ -77,8 +79,8 @@ public void unsafe_loop() { @Benchmark public void segment_loop_confined() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(ALLOC_SIZE, 4); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -87,8 +89,8 @@ public void segment_loop_confined() { @Benchmark public void segment_loop_shared() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = arena.allocate(ALLOC_SIZE, 4); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -133,7 +135,7 @@ public void buffer_loop_implicit() { @Benchmark public void segment_loop_implicit() { if (gcCount++ == 0) System.gc(); // GC when we overflow - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java index 5793b427074..2fd596d8a36 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java @@ -40,7 +40,7 @@ import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java index a287b1120f6..c5b697b8ac8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -40,7 +41,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -55,6 +56,8 @@ public class LoopOverNonConstant extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + + Arena arena; MemorySegment segment; long unsafe_addr; @@ -66,7 +69,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(unsafe_addr + (i * CARRIER_SIZE) , i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -78,7 +82,7 @@ public void setup() { @TearDown public void tearDown() { - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); unsafe.freeMemory(unsafe_addr); } @@ -157,24 +161,6 @@ public int segment_loop_instance_unaligned() { return res; } - @Benchmark - public int segment_loop_instance_address() { - int sum = 0; - for (int i = 0; i < ELEM_SIZE; i++) { - sum += segment.address().get(JAVA_INT, i * CARRIER_SIZE); - } - return sum; - } - - @Benchmark - public int segment_loop_instance_address_index() { - int sum = 0; - for (int i = 0; i < ELEM_SIZE; i++) { - sum += segment.address().getAtIndex(JAVA_INT, i); - } - return sum; - } - @Benchmark public int segment_loop_slice() { int sum = 0; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java index 65f818c71b1..430a3b69d04 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -56,7 +57,7 @@ public class LoopOverNonConstantFP { static final int CARRIER_SIZE = (int)JAVA_DOUBLE.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - MemorySession session; + Arena arena; MemorySegment segmentIn, segmentOut; long unsafe_addrIn, unsafe_addrOut; ByteBuffer byteBufferIn, byteBufferOut; @@ -71,9 +72,9 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putDouble(unsafe_addrOut + (i * CARRIER_SIZE), i); } - session = MemorySession.openConfined(); - segmentIn = MemorySegment.allocateNative(ALLOC_SIZE, session); - segmentOut = MemorySegment.allocateNative(ALLOC_SIZE, session); + arena = Arena.openConfined(); + segmentIn = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); + segmentOut = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { segmentIn.setAtIndex(JAVA_DOUBLE, i, i); } @@ -92,7 +93,7 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + arena.close(); unsafe.invokeCleaner(byteBufferIn); unsafe.invokeCleaner(byteBufferOut); unsafe.freeMemory(unsafe_addrIn); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java index c49c050cbe8..386fe2691ea 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java @@ -23,7 +23,7 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -37,14 +37,12 @@ import org.openjdk.jmh.annotations.Warmup; import sun.misc.Unsafe; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -78,7 +76,7 @@ public void setup() { MemorySegment intI = MemorySegment.ofArray(new int[ALLOC_SIZE]); MemorySegment intD = MemorySegment.ofArray(new double[ALLOC_SIZE]); MemorySegment intF = MemorySegment.ofArray(new float[ALLOC_SIZE]); - MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, MemorySession.openConfined()); + MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, SegmentScope.auto()); for (int i = 0; i < ALLOC_SIZE; i++) { intB.set(JAVA_BYTE, i, (byte)i); intI.setAtIndex(JAVA_INT, i, i); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java index f208586eb97..0572223f84e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -47,7 +48,7 @@ import java.nio.file.StandardOpenOption; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -78,6 +79,7 @@ public class LoopOverNonConstantMapped extends JavaLayouts { } FileChannel fileChannel; + Arena arena; MemorySegment segment; long unsafe_addr; @@ -93,14 +95,15 @@ public void setup() throws IOException { ((MappedByteBuffer)byteBuffer).force(); } fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE); - segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, ALLOC_SIZE, MemorySession.openConfined()); - unsafe_addr = segment.address().toRawLongValue(); + arena = Arena.openConfined(); + segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, ALLOC_SIZE, arena.scope()); + unsafe_addr = segment.address(); } @TearDown public void tearDown() throws IOException { fileChannel.close(); - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); } @@ -149,15 +152,6 @@ public int segment_loop_instance() { return res; } - @Benchmark - public int segment_loop_instance_address() { - int res = 0; - for (int i = 0; i < ELEM_SIZE; i ++) { - res += segment.address().get(JAVA_INT, i * CARRIER_SIZE); - } - return res; - } - @Benchmark public int segment_loop_slice() { int sum = 0; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java index dd61a3cf3b5..f3d47fed5d1 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -55,6 +56,7 @@ public class LoopOverNonConstantShared extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + Arena arena; MemorySegment segment; long unsafe_addr; @@ -66,7 +68,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(unsafe_addr + (i * CARRIER_SIZE) , i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -78,7 +81,7 @@ public void setup() { @TearDown public void tearDown() { - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); unsafe.freeMemory(unsafe_addr); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java new file mode 100644 index 00000000000..2463856fbdf --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, 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 org.openjdk.bench.java.lang.foreign; + +import java.lang.foreign.MemorySegment; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.SegmentScope; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = "--enable-preview") +public class LoopOverOfAddress extends JavaLayouts { + + static final int ITERATIONS = 1_000_000; + + @Benchmark + public long segment_loop_addr() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i % 100).address(); + } + return res; + } + + @Benchmark + public long segment_loop_addr_size() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i, i % 100).address(); + } + return res; + } + + @Benchmark + public long segment_loop_addr_size_session() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i, i % 100, SegmentScope.global()).address(); + } + return res; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java index 6ed7ab6bc29..425a1adce44 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -38,7 +39,7 @@ import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -55,7 +56,7 @@ public class LoopOverPollutedSegments extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; - MemorySession session; + Arena confinedArena, sharedArena; MemorySegment nativeSegment, nativeSharedSegment, heapSegmentBytes, heapSegmentFloats; byte[] arr; long addr; @@ -67,8 +68,10 @@ public void setup() { unsafe.putInt(addr + (i * 4), i); } arr = new byte[ALLOC_SIZE]; - nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session = MemorySession.openConfined()); - nativeSharedSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + confinedArena = Arena.openConfined(); + sharedArena = Arena.openShared(); + nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, confinedArena.scope()); + nativeSharedSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, sharedArena.scope()); heapSegmentBytes = MemorySegment.ofArray(new byte[ALLOC_SIZE]); heapSegmentFloats = MemorySegment.ofArray(new float[ELEM_SIZE]); @@ -92,7 +95,8 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + confinedArena.close(); + sharedArena.close(); heapSegmentBytes = null; heapSegmentFloats = null; arr = null; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java index 4c5e79c483a..23ac72d0e68 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -56,19 +57,22 @@ public class LoopOverSlice { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + Arena arena; MemorySegment nativeSegment, heapSegment; IntBuffer nativeBuffer, heapBuffer; @Setup public void setup() { - nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); heapSegment = MemorySegment.ofArray(new int[ELEM_SIZE]); nativeBuffer = ByteBuffer.allocateDirect(ALLOC_SIZE).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); heapBuffer = IntBuffer.wrap(new int[ELEM_SIZE]); } @TearDown - public void tearDown() { nativeSegment.session().close(); + public void tearDown() { + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java index e609da7fa7e..6df2fb0d6c1 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -36,10 +37,9 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @@ -104,27 +104,27 @@ public void tearDown() throws Throwable { @Benchmark public MemorySegment confined_close() { - try (MemorySession session = MemorySession.openConfined()) { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openConfined()) { + return arena.allocate(ALLOC_SIZE, 4); } } @Benchmark public MemorySegment shared_close() { - try (MemorySession session = MemorySession.openShared()) { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openShared()) { + return arena.allocate(ALLOC_SIZE, 4); } } @Benchmark public MemorySegment implicit_close() { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + return MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); } @Benchmark public MemorySegment implicit_close_systemgc() { if (gcCount++ == 0) System.gc(); // GC when we overflow - return MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + return MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); } // keep diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java index 05128cedbb7..78575b3c45c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java @@ -23,10 +23,11 @@ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; + import sun.misc.Unsafe; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -68,6 +69,7 @@ public class ParallelSum extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; + Arena arena; MemorySegment segment; long address; @@ -77,7 +79,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(address + (i * CARRIER_SIZE), i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, MemorySession.openShared()); + arena = Arena.openShared(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -86,7 +89,7 @@ public void setup() { @TearDown public void tearDown() throws Throwable { unsafe.freeMemory(address); - segment.session().close(); + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java index d7abdb72885..6f4aa4c17b6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java @@ -25,16 +25,14 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; @@ -54,8 +52,8 @@ @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) public class PointerInvoke extends CLayouts { - MemorySession session = MemorySession.openConfined(); - MemorySegment segment = MemorySegment.allocateNative(100, session); + Arena arena = Arena.openConfined(); + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); static { System.loadLibrary("Ptr"); @@ -66,35 +64,30 @@ public class PointerInvoke extends CLayouts { static { Linker abi = Linker.nativeLinker(); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); - F_LONG = abi.downcallHandle(loaderLibs.lookup("func_as_long").get(), + F_LONG = abi.downcallHandle(loaderLibs.find("func_as_long").get(), FunctionDescriptor.of(C_INT, C_LONG_LONG)); - F_PTR = abi.downcallHandle(loaderLibs.lookup("func_as_ptr").get(), + F_PTR = abi.downcallHandle(loaderLibs.find("func_as_ptr").get(), FunctionDescriptor.of(C_INT, C_POINTER)); } @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark public int panama_call_as_long() throws Throwable { - return (int)F_LONG.invokeExact(segment.address().toRawLongValue()); + return (int)F_LONG.invokeExact(segment.address()); } @Benchmark public int panama_call_as_address() throws Throwable { - return (int)F_PTR.invokeExact((Addressable)segment.address()); - } - - @Benchmark - public int panama_call_as_segment() throws Throwable { - return (int)F_PTR.invokeExact((Addressable)segment); + return (int)F_PTR.invokeExact(segment); } @Benchmark public int panama_call_as_new_segment() throws Throwable { - MemorySegment newSegment = MemorySegment.ofAddress(segment.address(), 100, session); - return (int)F_PTR.invokeExact((Addressable)newSegment); + MemorySegment newSegment = MemorySegment.ofAddress(segment.address(), 100, arena.scope()); + return (int)F_PTR.invokeExact(newSegment); } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java index 8fd2a64a34a..0b8b4e9708e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java @@ -22,13 +22,11 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -38,6 +36,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -56,17 +55,17 @@ public class QSort extends CLayouts { static final Linker abi = Linker.nativeLinker(); static final MethodHandle clib_qsort; - static final Addressable native_compar; - static final Addressable panama_upcall_compar; + static final MemorySegment native_compar; + static final MemorySegment panama_upcall_compar; static final long jni_upcall_compar; static final int[] INPUT = { 5, 3, 2, 7, 8, 12, 1, 7 }; static final MemorySegment INPUT_SEGMENT; - static Addressable qsort_addr = abi.defaultLookup().lookup("qsort").get(); + static MemorySegment qsort_addr = abi.defaultLookup().find("qsort").get(); static { - INPUT_SEGMENT = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(INPUT.length, JAVA_INT), MemorySession.global()); + INPUT_SEGMENT = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(INPUT.length, JAVA_INT), SegmentScope.global()); INPUT_SEGMENT.copyFrom(MemorySegment.ofArray(INPUT)); System.loadLibrary("QSortJNI"); @@ -78,13 +77,13 @@ public class QSort extends CLayouts { FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER) ); System.loadLibrary("QSort"); - native_compar = SymbolLookup.loaderLookup().lookup("compar").orElseThrow(); + native_compar = SymbolLookup.loaderLookup().find("compar").orElseThrow(); panama_upcall_compar = abi.upcallStub( lookup().findStatic(QSort.class, "panama_upcall_compar", - MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class)), + MethodType.methodType(int.class, MemorySegment.class, MemorySegment.class)), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER), - MemorySession.global() + SegmentScope.global() ); } catch (ReflectiveOperationException e) { throw new BootstrapMethodError(e); @@ -103,7 +102,7 @@ interface JNIComparator { @Benchmark public void native_qsort() throws Throwable { - clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)native_compar); + clib_qsort.invokeExact(INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), native_compar); } @Benchmark @@ -118,15 +117,11 @@ public void jni_upcall_qsort_naive() { @Benchmark public void panama_upcall_qsort() throws Throwable { - clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)panama_upcall_compar); - } - - private static int getIntAbsolute(MemoryAddress addr) { - return addr.get(JAVA_INT, 0); + clib_qsort.invokeExact(INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), panama_upcall_compar); } - static int panama_upcall_compar(MemoryAddress e0, MemoryAddress e1) { - return Integer.compare(getIntAbsolute(e0), getIntAbsolute(e1)); + static int panama_upcall_compar(MemorySegment e0, MemorySegment e1) { + return Integer.compare(e0.get(JAVA_INT, 0), e1.get(JAVA_INT, 0)); } static int jni_upcall_compar(int j0, int j1) { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java index 5ec95dce4f9..cd943a022f4 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java @@ -25,13 +25,13 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,10 +57,10 @@ @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) public class StrLenTest extends CLayouts { - MemorySession session = MemorySession.openConfined(); + Arena arena = Arena.openConfined(); SegmentAllocator segmentAllocator; - SegmentAllocator arenaAllocator = SegmentAllocator.newNativeArena(session); + SegmentAllocator arenaAllocator = new RingAllocator(arena.scope()); @Param({"5", "20", "100"}) public int size; @@ -74,19 +74,19 @@ public class StrLenTest extends CLayouts { static { Linker abi = Linker.nativeLinker(); - STRLEN = abi.downcallHandle(abi.defaultLookup().lookup("strlen").get(), + STRLEN = abi.downcallHandle(abi.defaultLookup().find("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); } @Setup public void setup() { str = makeString(size); - segmentAllocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(size + 1, MemorySession.openConfined())); + segmentAllocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(size + 1, arena.scope())); } @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark @@ -96,36 +96,35 @@ public int jni_strlen() throws Throwable { @Benchmark public int panama_strlen() throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(str.length() + 1, session); - segment.setUtf8String(0, str); - return (int)STRLEN.invokeExact((Addressable)segment); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocateUtf8String(str); + return (int)STRLEN.invokeExact(segment); } } @Benchmark - public int panama_strlen_arena() throws Throwable { - return (int)STRLEN.invokeExact((Addressable)arenaAllocator.allocateUtf8String(str)); + public int panama_strlen_ring() throws Throwable { + return (int)STRLEN.invokeExact(arenaAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_prefix() throws Throwable { - return (int)STRLEN.invokeExact((Addressable)segmentAllocator.allocateUtf8String(str)); + return (int)STRLEN.invokeExact(segmentAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_unsafe() throws Throwable { - MemoryAddress address = makeStringUnsafe(str); - int res = (int) STRLEN.invokeExact((Addressable)address); + MemorySegment address = makeStringUnsafe(str); + int res = (int) STRLEN.invokeExact(address); freeMemory(address); return res; } - static MemoryAddress makeStringUnsafe(String s) { + static MemorySegment makeStringUnsafe(String s) { byte[] bytes = s.getBytes(); int len = bytes.length; - MemoryAddress address = allocateMemory(len + 1); - MemorySegment str = MemorySegment.ofAddress(address, len + 1, MemorySession.global()); + MemorySegment address = allocateMemory(len + 1); + MemorySegment str = address.asSlice(0, len + 1); str.copyFrom(MemorySegment.ofArray(bytes)); str.set(JAVA_BYTE, len, (byte)0); return address; @@ -143,4 +142,31 @@ static String makeString(int size) { """; return lorem.substring(0, size); } + + static class RingAllocator implements SegmentAllocator { + final MemorySegment segment; + SegmentAllocator current; + long rem; + + public RingAllocator(SegmentScope session) { + this.segment = MemorySegment.allocateNative(1024, session); + reset(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + if (rem < byteSize) { + reset(); + } + MemorySegment res = current.allocate(byteSize, byteAlignment); + long lastOffset = segment.segmentOffset(res) + res.byteSize(); + rem = segment.byteSize() - lastOffset; + return res; + } + + void reset() { + current = SegmentAllocator.slicingAllocator(segment); + rem = segment.byteSize(); + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java index ec487cd75ad..c1ff656f780 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java @@ -24,7 +24,7 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -37,6 +37,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; @@ -67,7 +68,7 @@ public void setup() { } srcBufferNative = ByteBuffer.allocateDirect(size); - srcSegmentImplicit = MemorySegment.allocateNative(size, MemorySession.openImplicit()); + srcSegmentImplicit = MemorySegment.allocateNative(size, SegmentScope.auto()); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java index 709b6aec9c5..5586aa866c6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java @@ -24,6 +24,8 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; +import java.lang.invoke.VarHandle; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; @@ -31,7 +33,7 @@ import sun.misc.Unsafe; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -43,6 +45,10 @@ public class UnrolledAccess extends JavaLayouts { static final Unsafe U = Utils.unsafe; + static final VarHandle VH_LONG_UNALIGNED = JAVA_LONG_UNALIGNED.arrayElementVarHandle(); + + static final VarHandle VH_LONG = JAVA_LONG.arrayElementVarHandle(); + final static int SIZE = 1024; @State(Scope.Benchmark) @@ -61,8 +67,8 @@ public Data() { this.outputArray = new double[SIZE]; this.inputAddress = U.allocateMemory(8 * SIZE); this.outputAddress = U.allocateMemory(8 * SIZE); - this.inputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(inputAddress), 8*SIZE, MemorySession.global()); - this.outputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(outputAddress), 8*SIZE, MemorySession.global()); + this.inputSegment = MemorySegment.ofAddress(inputAddress, 8*SIZE, SegmentScope.global()); + this.outputSegment = MemorySegment.ofAddress(outputAddress, 8*SIZE, SegmentScope.global()); } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java index f40c3c5916e..ed79a30b6e8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java @@ -22,10 +22,10 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.MemorySegment; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -35,6 +35,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -56,10 +57,10 @@ public class Upcalls extends CLayouts { static final MethodHandle args5; static final MethodHandle args10; - static final Addressable cb_blank; - static final Addressable cb_identity; - static final Addressable cb_args5; - static final Addressable cb_args10; + static final MemorySegment cb_blank; + static final MemorySegment cb_identity; + static final MemorySegment cb_args5; + static final MemorySegment cb_args10; static final long cb_blank_jni; static final long cb_identity_jni; @@ -122,15 +123,15 @@ public class Upcalls extends CLayouts { static MethodHandle linkFunc(String name, FunctionDescriptor baseDesc) { return abi.downcallHandle( - SymbolLookup.loaderLookup().lookup(name).orElseThrow(), + SymbolLookup.loaderLookup().find(name).orElseThrow(), baseDesc.appendArgumentLayouts(C_POINTER) ); } - static Addressable makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { + static MemorySegment makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { return abi.upcallStub( lookup().findStatic(Upcalls.class, name, mt), - fd, MemorySession.global() + fd, SegmentScope.global() ); } @@ -147,7 +148,7 @@ public void jni_blank() throws Throwable { @Benchmark public void panama_blank() throws Throwable { - blank.invokeExact((Addressable)cb_blank); + blank.invokeExact(cb_blank); } @Benchmark @@ -167,17 +168,17 @@ public void jni_args10() throws Throwable { @Benchmark public int panama_identity() throws Throwable { - return (int) identity.invokeExact(10, (Addressable)cb_identity); + return (int) identity.invokeExact(10, cb_identity); } @Benchmark public void panama_args5() throws Throwable { - args5.invokeExact(1L, 2D, 3L, 4D, 5L, (Addressable)cb_args5); + args5.invokeExact(1L, 2D, 3L, 4D, 5L, cb_args5); } @Benchmark public void panama_args10() throws Throwable { - args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, (Addressable)cb_args10); + args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, cb_args10); } static void blank() {} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java b/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java index 46815f565dd..a9205c22515 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java @@ -22,10 +22,10 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,9 +57,10 @@ public class VaList extends CLayouts { static { SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); - MH_ellipsis = linker.downcallHandle(loaderLibs.lookup("ellipsis").get(), - FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_DOUBLE, C_LONG_LONG)); - MH_vaList = linker.downcallHandle(loaderLibs.lookup("vaList").get(), + MH_ellipsis = linker.downcallHandle(loaderLibs.find("ellipsis").get(), + FunctionDescriptor.ofVoid(C_INT, C_INT, C_DOUBLE, C_LONG_LONG), + Linker.Option.firstVariadicArg(1)); + MH_vaList = linker.downcallHandle(loaderLibs.find("vaList").get(), FunctionDescriptor.ofVoid(C_INT, C_POINTER)); } @@ -71,13 +72,13 @@ public void ellipsis() throws Throwable { @Benchmark public void vaList() throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { java.lang.foreign.VaList vaList = java.lang.foreign.VaList.make(b -> b.addVarg(C_INT, 1) .addVarg(C_DOUBLE, 2D) - .addVarg(C_LONG_LONG, 3L), session); + .addVarg(C_LONG_LONG, 3L), arena.scope()); MH_vaList.invokeExact(3, - (Addressable)vaList); + vaList.segment()); } } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java index 574bfdc27a8..e6501eae35f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,16 +58,18 @@ public class VarHandleExact { exact = generic.withInvokeExactBehavior(); } + Arena arena; MemorySegment data; @Setup public void setup() { - data = MemorySegment.allocateNative(JAVA_INT, MemorySession.openConfined()); + arena = Arena.openConfined(); + data = MemorySegment.allocateNative(JAVA_INT, arena.scope()); } @TearDown public void tearDown() { - data.session().close(); + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java new file mode 100644 index 00000000000..159464db390 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021, 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 org.openjdk.bench.java.lang.foreign.pointers; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; + +public sealed abstract class NativeType { + + public abstract MemoryLayout layout(); + + public non-sealed static abstract class OfInt extends NativeType { + public abstract ValueLayout.OfInt layout(); + } + public non-sealed static abstract class OfDouble extends NativeType { + public abstract ValueLayout.OfDouble layout(); + } + + private static final ValueLayout.OfAddress UNSAFE_ADDRESS = ValueLayout.ADDRESS.asUnbounded(); + + public final static class OfPointer extends NativeType { + public ValueLayout.OfAddress layout() { + return UNSAFE_ADDRESS; + } + } + + public non-sealed static abstract class OfStruct extends NativeType { + public abstract GroupLayout layout(); + public abstract X make(Pointer ptr); + } + + public static final OfInt C_INT = new OfInt<>() { + @Override + public ValueLayout.OfInt layout() { + return ValueLayout.JAVA_INT; + } + }; + + public static final OfDouble C_DOUBLE = new OfDouble<>() { + @Override + public ValueLayout.OfDouble layout() { + return ValueLayout.JAVA_DOUBLE; + } + }; + + @SuppressWarnings("unchecked") + final static OfPointer C_VOID_PTR = new OfPointer(); + + @SuppressWarnings("unchecked") + public static final OfPointer> C_INT_PTR = NativeType.C_VOID_PTR; + @SuppressWarnings("unchecked") + public static final OfPointer> C_DOUBLE_PTR = NativeType.C_VOID_PTR; + + + + @SuppressWarnings("unchecked") + public static OfPointer> ptr(NativeType type) { + return NativeType.C_VOID_PTR; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java new file mode 100644 index 00000000000..223cdf66652 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, 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 org.openjdk.bench.java.lang.foreign.pointers; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; + +public class Point extends Struct { + + Point(Pointer ptr) { + super(ptr); + } + + int x() { + return ptr.segment.get(NativeType.C_INT.layout(), 0); + } + int y() { + return ptr.segment.get(NativeType.C_INT.layout(), 4); + } + + static Point wrap(MemorySegment segment) { + return new Point(Pointer.wrap(TYPE, segment)); + } + + static final NativeType.OfStruct TYPE = new NativeType.OfStruct() { + static final GroupLayout LAYOUT = MemoryLayout.structLayout( + ValueLayout.JAVA_INT.withName("x"), + ValueLayout.JAVA_INT.withName("y")); + + @Override + public GroupLayout layout() { + return LAYOUT; + } + + @Override + public Point make(Pointer pointer) { + return new Point(pointer); + } + }; +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java new file mode 100644 index 00000000000..13a96a2ab59 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021, 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 org.openjdk.bench.java.lang.foreign.pointers; + + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; + +public class Pointer { + + final MemorySegment segment; + + Pointer(MemorySegment segment) { + this.segment = segment; + } + + public > int get(Z type, long index) { + return segment.getAtIndex(type.layout(), index); + } + + public > double get(Z type, long index) { + return segment.getAtIndex(type.layout(), index); + } + + public > X get(Z type, long index) { + return type.make(addOffset(index * type.layout().byteSize())); + } + + public Pointer addOffset(long offset) { + return new Pointer<>(segment.asSlice(offset)); + } + + @SuppressWarnings("unchecked") + public > X get(Z type, long index) { + MemorySegment address = segment.getAtIndex(type.layout(), index); + return (X)new Pointer<>(address); + } + + @SuppressWarnings("unchecked") + public X get(NativeType type, long offset) { + if (type instanceof NativeType.OfInt intType) { + return (X) (Object) get(intType, offset); + } else if (type instanceof NativeType.OfDouble doubleType) { + return (X) (Object) get(doubleType, offset); + } else { + throw new UnsupportedOperationException(); + } + } + + public MemorySegment segment() { + return segment; + } + + public static Pointer allocate(NativeType type, SegmentAllocator allocator) { + MemorySegment segment = allocator.allocate(type.layout()); + return new Pointer<>(segment); + } + + public static Pointer allocate(NativeType type, long size, SegmentAllocator allocator) { + MemorySegment segment = allocator.allocateArray(type.layout(), size); + return new Pointer<>(segment); + } + + public static Pointer wrap(NativeType type, MemorySegment segment) { + return new Pointer<>(segment); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java new file mode 100644 index 00000000000..1a1d196c2ae --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, 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 org.openjdk.bench.java.lang.foreign.pointers; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@State(Scope.Benchmark) +public class PointerBench { + + final Arena arena = Arena.openConfined(); + static final int ELEM_SIZE = 1_000_000; + Pointer intPointer = Pointer.allocate(NativeType.C_INT, ELEM_SIZE, arena); + Pointer> intPointerPointer = Pointer.allocate(NativeType.C_INT_PTR, ELEM_SIZE, arena); + Pointer pointPointer = Pointer.allocate(Point.TYPE, ELEM_SIZE, arena); + MemorySegment intSegment = intPointer.segment(); + MemorySegment intPointerSegment = intPointerPointer.segment(); + MemorySegment pointSegment = pointPointer.segment(); + + public static final ValueLayout.OfAddress UNSAFE_ADDRESS = ValueLayout.ADDRESS.asUnbounded(); + + @Setup + public void setup() { + for (int i = 0 ; i < ELEM_SIZE ; i++) { + intSegment.setAtIndex(ValueLayout.JAVA_INT, i, i); + intPointerSegment.setAtIndex(ValueLayout.ADDRESS, i, intSegment.asSlice(4 * i)); + pointSegment.setAtIndex(ValueLayout.JAVA_INT, (i * 2), i); + pointSegment.setAtIndex(ValueLayout.JAVA_INT, (i * 2) + 1, i); + } + } + + @TearDown + public void teardown() { + arena.close(); + } + + @Benchmark + public int testLoopPointerInt_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intPointer.get(NativeType.C_INT, i); + } + return sum; + } + + @Benchmark + public int testLoopPointerPointerInt_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intPointerPointer.get(NativeType.C_INT_PTR, i) + .get(NativeType.C_INT, 0); + } + return sum; + } + + @Benchmark + public int testLoopPointerPoint_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += pointPointer.get(Point.TYPE, i).x(); + } + return sum; + } + + @Benchmark + public int testLoopPointerInt_ptr_generic() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += genericGet(intPointer, NativeType.C_INT, i); + } + return sum; + } + + static Z genericGet(Pointer pz, NativeType type, long offset) { + return pz.get(type, offset); + } + + @Benchmark + public int testLoopPointerInt_segment() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intSegment.getAtIndex(ValueLayout.JAVA_INT, i); + } + return sum; + } + + @Benchmark + public int testLoopPointerPointerInt_segment() { + int sum = 0; + for (long i = 0 ; i < ELEM_SIZE ; i++) { + var segment = intPointerSegment.getAtIndex(UNSAFE_ADDRESS, i); + sum += segment.get(ValueLayout.JAVA_INT, 0); + } + return sum; + } + + @Benchmark + public int testLoopPointerPoint_segment() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += pointSegment.getAtIndex(ValueLayout.JAVA_INT, i * 2); + } + return sum; + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java similarity index 76% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java rename to test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java index 30564238287..f9a0c05b377 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -19,17 +19,14 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ -package sun.jvm.hotspot.gc.shared; - -import sun.jvm.hotspot.debugger.*; +package org.openjdk.bench.java.lang.foreign.pointers; -/** No additional functionality for now */ +public abstract class Struct> { + protected final Pointer ptr; -public class OffsetTableContigSpace extends ContiguousSpace { - public OffsetTableContigSpace(Address addr) { - super(addr); - } + public Struct(Pointer ptr) { + this.ptr = ptr; + } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java index 4f5fe751a98..1ed1d7a899c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java @@ -22,12 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign.points.support; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.bench.java.lang.foreign.CLayouts; import java.lang.foreign.SymbolLookup; @@ -53,19 +53,21 @@ public class PanamaPoint extends CLayouts implements AutoCloseable { System.loadLibrary("Point"); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); MH_distance = abi.downcallHandle( - loaderLibs.lookup("distance").get(), + loaderLibs.find("distance").get(), FunctionDescriptor.of(C_DOUBLE, LAYOUT, LAYOUT) ); MH_distance_ptrs = abi.downcallHandle( - loaderLibs.lookup("distance_ptrs").get(), + loaderLibs.find("distance_ptrs").get(), FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_POINTER) ); } + Arena arena; private final MemorySegment segment; public PanamaPoint(int x, int y) { - this.segment = MemorySegment.allocateNative(LAYOUT, MemorySession.openConfined()); + this.arena = Arena.openConfined(); + this.segment = MemorySegment.allocateNative(LAYOUT, arena.scope()); setX(x); setY(y); } @@ -96,7 +98,7 @@ public double distanceTo(PanamaPoint other) { public double distanceToPtrs(PanamaPoint other) { try { - return (double) MH_distance_ptrs.invokeExact((Addressable)segment, (Addressable)other.segment); + return (double) MH_distance_ptrs.invokeExact(segment, other.segment); } catch (Throwable throwable) { throw new InternalError(throwable); } @@ -104,6 +106,6 @@ public double distanceToPtrs(PanamaPoint other) { @Override public void close() { - segment.session().close(); + arena.close(); } } diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java new file mode 100644 index 00000000000..69d379a8a83 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 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 org.openjdk.bench.javax.crypto.full; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +/** + * This performance test runs AES/GCM encryption and decryption using CipherInputStream. + * + * This test rotates the IV and creates a new GCMParameterSpec for each encrypt + * benchmark operation + */ + +public class AESGCMCipherInputStream extends CryptoBase { + + @Param({"128"}) + private int keyLength; + + @Param({"16384", "1048576"}) + private int dataSize; + + byte[] encryptedData; + byte[] in; + ByteArrayOutputStream out; + private Cipher encryptCipher; + private Cipher decryptCipher; + SecretKeySpec ks; + GCMParameterSpec gcm_spec; + byte[] iv; + + private static final int IV_BUFFER_SIZE = 32; + private static final int IV_MODULO = IV_BUFFER_SIZE - 16; + int iv_index = 0; + + private int next_iv_index() { + int r = iv_index; + iv_index = (iv_index + 1) % IV_MODULO; + return r; + } + + @Setup + public void setup() throws Exception { + setupProvider(); + + // Setup key material + byte[] keystring = fillSecureRandom(new byte[keyLength / 8]); + ks = new SecretKeySpec(keystring, "AES"); + iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + + // Setup Cipher classes + encryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + decryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + + // Setup input/output buffers + in = fillRandom(new byte[dataSize]); + encryptedData = new byte[encryptCipher.getOutputSize(in.length)]; + out = new ByteArrayOutputStream(encryptedData.length); + encryptCipher.doFinal(in, 0, in.length, encryptedData, 0); + } + + @Benchmark + public byte[] encrypt() throws Exception { + out.reset(); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + ByteArrayInputStream fin = new ByteArrayInputStream(in); + InputStream cin = new CipherInputStream(fin, encryptCipher); + + cin.transferTo(out); + return out.toByteArray(); + } + + @Benchmark + public byte[] decrypt() throws Exception { + out.reset(); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + ByteArrayInputStream fin = new ByteArrayInputStream(encryptedData); + InputStream cin = new CipherInputStream(fin, decryptCipher); + + cin.transferTo(out); + return out.toByteArray(); + } +} diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherOutputStream.java b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherOutputStream.java new file mode 100644 index 00000000000..cf1e8bf3c56 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherOutputStream.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 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 org.openjdk.bench.javax.crypto.full; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; + +import javax.crypto.Cipher; +import javax.crypto.CipherOutputStream; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +/** + * This performance test runs AES/GCM encryption and decryption using CipherOutputStream. + * + * This test rotates the IV and creates a new GCMParameterSpec for each encrypt + * benchmark operation + */ + +public class AESGCMCipherOutputStream extends CryptoBase { + + @Param({"128"}) + private int keyLength; + + @Param({"16384", "1048576"}) + private int dataSize; + + byte[] encryptedData; + byte[] in; + ByteArrayOutputStream out; + private Cipher encryptCipher; + private Cipher decryptCipher; + SecretKeySpec ks; + GCMParameterSpec gcm_spec; + byte[] iv; + + private static final int IV_BUFFER_SIZE = 32; + private static final int IV_MODULO = IV_BUFFER_SIZE - 16; + int iv_index = 0; + + private int next_iv_index() { + int r = iv_index; + iv_index = (iv_index + 1) % IV_MODULO; + return r; + } + + @Setup + public void setup() throws Exception { + setupProvider(); + + // Setup key material + byte[] keystring = fillSecureRandom(new byte[keyLength / 8]); + ks = new SecretKeySpec(keystring, "AES"); + iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + + // Setup Cipher classes + encryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + decryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + + // Setup input/output buffers + in = fillRandom(new byte[dataSize]); + encryptedData = new byte[encryptCipher.getOutputSize(in.length)]; + out = new ByteArrayOutputStream(encryptedData.length); + encryptCipher.doFinal(in, 0, in.length, encryptedData, 0); + } + + @Benchmark + public byte[] encrypt() throws Exception { + out.reset(); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + + OutputStream cout = new CipherOutputStream(out, encryptCipher); + for (int i = 0; i < in.length; i += 512) { + cout.write(in, i, Math.min(512, in.length - i)); + } + cout.close(); + return out.toByteArray(); + } + + @Benchmark + public byte[] decrypt() throws Exception { + out.reset(); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + OutputStream cout = new CipherOutputStream(out, decryptCipher); + for (int i = 0; i < encryptedData.length; i += 512) { + cout.write(encryptedData, i, Math.min(512, encryptedData.length - i)); + } + cout.close(); + return out.toByteArray(); + } +} diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java b/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java index aa45aa2e398..15613557fb9 100644 --- a/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java +++ b/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java @@ -37,6 +37,7 @@ import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.annotations.Measurement; +import java.nio.ByteBuffer; @Measurement(iterations = 3, time = 10) @Warmup(iterations = 3, time = 10) @@ -49,7 +50,7 @@ public class Poly1305DigestBench extends CryptoBase { private byte[][] data; int index = 0; - private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineFinal; + private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineUpdateBuf, polyEngineFinal; private static Object polyObj; static { @@ -68,6 +69,10 @@ public class Poly1305DigestBench extends CryptoBase { m.setAccessible(true); polyEngineUpdate = lookup.unreflect(m); + m = polyClazz.getDeclaredMethod("engineUpdate", ByteBuffer.class); + m.setAccessible(true); + polyEngineUpdateBuf = lookup.unreflect(m); + m = polyClazz.getDeclaredMethod("engineDoFinal"); m.setAccessible(true); polyEngineFinal = lookup.unreflect(m); @@ -83,7 +88,7 @@ public void setup() { } @Benchmark - public byte[] digest() { + public byte[] digestBytes() { try { byte[] d = data[index]; index = (index +1) % SET_SIZE; @@ -94,4 +99,17 @@ public byte[] digest() { throw new RuntimeException(ex); } } + + @Benchmark + public byte[] digestBuffer() { + try { + byte[] d = data[index]; + index = (index +1) % SET_SIZE; + polyEngineInit.invoke(polyObj, new SecretKeySpec(d, 0, 32, "Poly1305"), null); + polyEngineUpdateBuf.invoke(polyObj, ByteBuffer.wrap(d, 0, d.length)); + return (byte[])polyEngineFinal.invoke(polyObj); + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java new file mode 100644 index 00000000000..ab08dc8919c --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2022, 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. + */ + + +package org.openjdk.bench.jdk.incubator.concurrent; + +import jdk.incubator.concurrent.ScopedValue; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import static org.openjdk.bench.jdk.incubator.concurrent.ScopedValuesData.*; + +/** + * Tests ScopedValue + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations=4, time=1) +@Measurement(iterations=10, time=1) +@Threads(1) +@Fork(value = 1, + jvmArgsPrepend = {"-Djmh.executor.class=org.openjdk.bench.jdk.incubator.concurrent.ScopedValuesExecutorService", + "-Djmh.executor=CUSTOM", + "-Djmh.blackhole.mode=COMPILER", + "--add-modules=jdk.incubator.concurrent", + "--enable-preview"}) +@State(Scope.Thread) +@SuppressWarnings("preview") +public class ScopedValues { + + private static final Integer THE_ANSWER = 42; + + // Test 1: make sure ScopedValue.get() is hoisted out of loops. + + @Benchmark + public void thousandAdds_ScopedValue(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.sl1.get(); + } + bh.consume(result); + } + + @Benchmark + public void thousandAdds_ThreadLocal(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.tl1.get(); + } + bh.consume(result); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int thousandIsBoundQueries(Blackhole bh) throws Exception { + var result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.sl1.isBound() ? 1 : 0; + } + return result; + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int thousandMaybeGets(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + if (ScopedValuesData.sl1.isBound()) { + result += ScopedValuesData.sl1.get(); + } + } + return result; + } + + // Test 2: stress the ScopedValue cache. + // The idea here is to use a bunch of bound values cyclically, which + // stresses the ScopedValue cache. + + int combine(int n, int i1, int i2, int i3, int i4, int i5, int i6) { + return n + ((i1 ^ i2 >>> 6) + (i3 << 7) + i4 - i5 | i6); + } + + @Benchmark + public int sixValues_ScopedValue() throws Exception { + int result = 0; + for (int i = 0 ; i < 166; i++) { + result = combine(result, sl1.get(), sl2.get(), sl3.get(), sl4.get(), sl5.get(), sl6.get()); + } + return result; + } + + @Benchmark + public int sixValues_ThreadLocal() throws Exception { + int result = 0; + for (int i = 0 ; i < 166; i++) { + result = combine(result, tl1.get(), tl2.get(), tl3.get(), tl4.get(), tl5.get(), tl6.get()); + } + return result; + } + + // Test 3: The cost of bind, then get + // This is the worst case for ScopedValues because we have to create + // a binding, link it in, then search the current bindings. In addition, we + // create a cache entry for the bound value, then we immediately have to + // destroy it. + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int CreateBindThenGetThenRemove_ScopedValue() throws Exception { + return ScopedValue.where(sl1, THE_ANSWER).call(sl1::get); + } + + + // Create a Carrier ahead of time: might be slightly faster + private static final ScopedValue.Carrier HOLD_42 = ScopedValue.where(sl1, 42); + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetThenRemove_ScopedValue() throws Exception { + return HOLD_42.call(sl1::get); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetThenRemove_ThreadLocal() throws Exception { + try { + tl1.set(THE_ANSWER); + return tl1.get(); + } finally { + tl1.remove(); + } + } + + // This has no exact equivalent in ScopedValue, but it's provided here for + // information. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetNoRemove_ThreadLocal() throws Exception { + tl1.set(THE_ANSWER); + return tl1.get(); + } + + // Test 4: The cost of binding, but not using any result + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Object bind_ScopedValue() throws Exception { + return HOLD_42.call(this::getClass); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Object bind_ThreadLocal() throws Exception { + try { + tl1.set(THE_ANSWER); + return this.getClass(); + } finally { + tl1.remove(); + } + } + + // Simply set a ThreadLocal so that the caller can see it + // This has no exact equivalent in ScopedValue, but it's provided here for + // information. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void setNoRemove_ThreadLocal() throws Exception { + tl1.set(THE_ANSWER); + } + + // This is the closest I can think of to setNoRemove_ThreadLocal in that it + // returns a value in a ScopedValue container. The container must already + // be bound to an AtomicReference for this to work. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void setNoRemove_ScopedValue() throws Exception { + sl_atomicRef.get().setPlain(THE_ANSWER); + } + + // Test 5: A simple counter + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void counter_ScopedValue() { + sl_atomicInt.get().setPlain( + sl_atomicInt.get().getPlain() + 1); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void counter_ThreadLocal() { + // Very slow: + // tl1.set(tl1.get() + 1); + var ctr = tl_atomicInt.get(); + ctr.setPlain(ctr.getPlain() + 1); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java new file mode 100644 index 00000000000..29e007d3483 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, 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. + */ + +package org.openjdk.bench.jdk.incubator.concurrent; + +import jdk.incubator.concurrent.ScopedValue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +@SuppressWarnings("preview") +public class ScopedValuesData { + + static final ScopedValue sl1 = ScopedValue.newInstance(); + static final ThreadLocal tl1 = new ThreadLocal<>(); + + static final ScopedValue sl2 = ScopedValue.newInstance(); + static final ScopedValue sl3 = ScopedValue.newInstance(); + static final ScopedValue sl4 = ScopedValue.newInstance(); + static final ScopedValue sl5 = ScopedValue.newInstance(); + static final ScopedValue sl6 = ScopedValue.newInstance(); + static final ScopedValue sl_atomicInt = ScopedValue.newInstance(); + + static final ScopedValue unbound = ScopedValue.newInstance(); + + static final ScopedValue> sl_atomicRef = ScopedValue.newInstance(); + + static final ThreadLocal tl2 = new ThreadLocal<>(); + static final ThreadLocal tl3 = new ThreadLocal<>(); + static final ThreadLocal tl4 = new ThreadLocal<>(); + static final ThreadLocal tl5 = new ThreadLocal<>(); + static final ThreadLocal tl6 = new ThreadLocal<>(); + static final ThreadLocal tl_atomicInt = new ThreadLocal<>(); + + static final ScopedValue.Carrier VALUES = ScopedValue + .where(sl1, 42).where(sl2, 2).where(sl3, 3) + .where(sl4, 4).where(sl5, 5).where(sl6, 6); + + public static void run(Runnable action) { + try { + tl1.set(42); tl2.set(2); tl3.set(3); tl4.set(4); tl5.set(5); tl6.set(6); + tl1.get(); // Create the ScopedValue cache as a side effect + tl_atomicInt.set(new AtomicInteger()); + VALUES.where(sl_atomicInt, new AtomicInteger()) + .where(sl_atomicRef, new AtomicReference<>()) + .run(action); + } finally { + tl1.remove(); tl2.remove(); tl3.remove(); tl4.remove(); tl5.remove(); tl6.remove(); + tl_atomicInt.remove(); + } + } +} + diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java new file mode 100644 index 00000000000..5238dbcc665 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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 org.openjdk.bench.jdk.incubator.concurrent; + +import java.util.concurrent.*; + +public class ScopedValuesExecutorService extends ThreadPoolExecutor { + public ScopedValuesExecutorService(int corePoolSize, String prefix) { + super(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), + new AThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); + } +} + +class AThreadFactory implements ThreadFactory { + public Thread newThread(Runnable action) { + return new Thread() { + public void run() { + ScopedValuesData.run(action); + } + }; + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java index a73beddfe87..4f6c4aa65f2 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java @@ -26,7 +26,7 @@ package org.openjdk.bench.jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import jdk.incubator.vector.ByteVector; @@ -69,8 +69,8 @@ public class MemorySegmentVectorAccess { @Setup public void setup() { - nativeIn = MemorySegment.allocateNative(size, MemorySession.openImplicit()); - nativeOut = MemorySegment.allocateNative(size, MemorySession.openImplicit()); + nativeIn = MemorySegment.allocateNative(size, SegmentScope.auto()); + nativeOut = MemorySegment.allocateNative(size, SegmentScope.auto()); byteIn = new byte[size]; byteOut = new byte[size]; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java index d28c860ebe0..62735fa3b00 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java @@ -23,9 +23,9 @@ */ package org.openjdk.bench.jdk.incubator.vector; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import jdk.incubator.vector.ByteVector; @@ -43,8 +43,6 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; - @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -70,18 +68,10 @@ public class TestLoadStoreBytes { private MemorySegment dstSegmentHeap; - - private MemorySession implicitScope; - private MemorySegment srcSegment; private MemorySegment dstSegment; - - private MemoryAddress srcAddress; - - private MemoryAddress dstAddress; - private byte[] a, b, c; @Setup @@ -95,12 +85,8 @@ public void setup() { srcSegmentHeap = MemorySegment.ofArray(new byte[size]); dstSegmentHeap = MemorySegment.ofArray(new byte[size]); - implicitScope = MemorySession.openImplicit(); - srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - - srcAddress = srcSegment.address(); - dstAddress = dstSegment.address(); + srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); + dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); a = new byte[size]; b = new byte[size]; @@ -177,9 +163,9 @@ public void segmentNativeImplicit() { @Benchmark public void segmentNativeConfined() { - try (final var session = MemorySession.openConfined()) { - final var srcSegmentConfined = MemorySegment.ofAddress(srcAddress, size, session); - final var dstSegmentConfined = MemorySegment.ofAddress(dstAddress, size, session); + try (final var arena = Arena.openConfined()) { + final var srcSegmentConfined = MemorySegment.ofAddress(srcSegment.address(), size, arena.scope()); + final var dstSegmentConfined = MemorySegment.ofAddress(dstSegment.address(), size, arena.scope()); for (long i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ByteVector.fromMemorySegment(SPECIES, srcSegmentConfined, i, ByteOrder.nativeOrder()); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java index ef6f2bb4ed4..ecbe5889806 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java @@ -23,12 +23,13 @@ */ package org.openjdk.bench.jdk.incubator.vector; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorOperators; import jdk.incubator.vector.VectorSpecies; @@ -71,18 +72,10 @@ public class TestLoadStoreShorts { private MemorySegment dstSegmentHeap; - - private MemorySession implicitScope; - private MemorySegment srcSegment; private MemorySegment dstSegment; - - private MemoryAddress srcAddress; - - private MemoryAddress dstAddress; - private short[] a, b, c; @Setup @@ -97,12 +90,8 @@ public void setup() { srcSegmentHeap = MemorySegment.ofArray(new byte[size]); dstSegmentHeap = MemorySegment.ofArray(new byte[size]); - implicitScope = MemorySession.openImplicit(); - srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - - srcAddress = srcSegment.address(); - dstAddress = dstSegment.address(); + srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); + dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); this.longSize = longSize; @@ -172,9 +161,9 @@ public void segmentNativeImplicit() { @Benchmark public void segmentNativeConfined() { - try (final var session = MemorySession.openConfined()) { - final var srcSegmentConfined = MemorySegment.ofAddress(srcAddress, size, session); - final var dstSegmentConfined = MemorySegment.ofAddress(dstAddress, size, session); + try (final var arena = Arena.openConfined()) { + final var srcSegmentConfined = MemorySegment.ofAddress(srcSegment.address(), size, arena.scope()); + final var dstSegmentConfined = MemorySegment.ofAddress(dstSegment.address(), size, arena.scope()); for (long i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ShortVector.fromMemorySegment(SPECIES, srcSegmentConfined, i, ByteOrder.nativeOrder()); diff --git a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java index 59920591f67..e313b948c9f 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java +++ b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -44,250 +44,132 @@ @Fork(value = 3) public class InterfaceCalls { - interface AnInterface { - public int getInt(); + interface FirstInterface { + public int getIntFirst(); } interface SecondInterface { - public int get1(); + public int getIntSecond(); } - interface OnlyHasOneImplInterface { - public int getLong(); - } - - interface AloneInterface { - public int getNumber(); - } - - class SingleImplementor implements OnlyHasOneImplInterface { - public int getLong() { + class FirstClass implements FirstInterface, SecondInterface { + public int getIntFirst() { return 1; } - } - - class Extender1 extends SingleImplementor { - } - class FirstClass implements AnInterface { - public int getInt() { + public int getIntSecond() { return 1; } } - class SecondClass implements AnInterface { - public int getInt() { + class SecondClass implements FirstInterface, SecondInterface { + public int getIntFirst() { return 2; } - } - class ThirdClass implements AnInterface { - public int getInt() { - return -3; + public int getIntSecond() { + return 1; } } - class FourthClass implements AnInterface { - public int getInt() { - return -4; + class ThirdClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -3; } - } - class FifthClass implements AnInterface { - public int getInt() { - return -5; + public int getIntSecond() { + return 1; } } - class MultiClass1 implements AnInterface, SecondInterface { - public int get1() { - return 1; + class FourthClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -4; } - public int getInt() { - return 2; + public int getIntSecond() { + return 1; } } - class MultiClass2 implements AnInterface, SecondInterface { - public int get1() { - return -1; - } - - public int getInt() { - return -2; + class FifthClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -5; } - } - class Aloner implements AloneInterface { - public int getNumber() { - return 7; + public int getIntSecond() { + return 1; } } - public Object dummy1; - - public Object dummy2; - - public Object dummy3; - - public AnInterface multi1a, multi2a; - - public SecondInterface multi1b, multi2b; - - public Object multic, multic2; - - public AnInterface[] as = new AnInterface[5]; - - public AnInterface multi; - - public OnlyHasOneImplInterface single1; + final int asLength = 5; + public FirstInterface[] as = new FirstInterface[asLength]; - public OnlyHasOneImplInterface single2; - - public AloneInterface alone; - - int count; @Setup public void setupSubclass() { - dummy1 = new FirstClass(); - dummy2 = new SecondClass(); - dummy3 = new ThirdClass(); as[0] = new FirstClass(); as[1] = new SecondClass(); as[2] = new ThirdClass(); as[3] = new FourthClass(); as[4] = new FifthClass(); - MultiClass1 mc1 = new MultiClass1(); - multi1a = mc1; - multi1b = mc1; - multic = mc1; - MultiClass2 mc2 = new MultiClass2(); - multi2a = mc2; - multi2b = mc2; - multic2 = mc2; - single1 = new SingleImplementor(); - single2 = new Extender1(); - alone = new Aloner(); - } - - private void swapMultiParts() { - AnInterface tmpa = multi1a; - SecondInterface tmpb = multi1b; - multi1a = multi2a; - multi2a = tmpa; - multi1b = multi2b; - multi2b = tmpb; - } - - @SuppressWarnings("unused") - private void swapMulti() { - Object tmp = multic; - multic = multic2; - multic2 = tmp; } /** - * Tests a call where there are multiple implementors but only one of the implementors is every used here so the - * call-site is monomorphic + * Tests a call where there are multiple implementors but only one of the + * implementors is every used here so the call-site is monomorphic */ @Benchmark public int testMonomorphic() { - return as[0].getInt(); - } - - /** Tests a interface call that only has one single implementation */ - @Benchmark - public int testSingle() { - return alone.getNumber(); + return as[0].getIntFirst(); } - /** - * Tests a call where there is a single implementation but multiple classes that inherit that implementation and both - * these implementors are used. - */ - @Benchmark - public int testSingle2() { - OnlyHasOneImplInterface oi; - if ((count & 1) == 0) { - oi = single1; - } else { - oi = single2; - } - count++; - return oi.getLong(); - } + int l = 0; /** - * Tests calling two different interface methods in two different interfaces on the same receiver. Make sure to switch - * between two different types of receivers to achieve polymorhpism + * Interface call address computation within loop but the receiver preexists + * the loop and the ac can be moved outside of the loop */ @Benchmark - public void testCall2Poly2(Blackhole bh) { - bh.consume(multi1a.getInt()); - bh.consume(multi1b.get1()); - swapMultiParts(); - } - - @Benchmark - public int testCallMulti1Poly2NoSwap() { - return multi1a.getInt(); + public int test1stInt2Types() { + FirstInterface ai = as[l]; + l = 1 - l; + return ai.getIntFirst(); } - /** - * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different - * interfaces take different amounts of time (They do for hotspot) - */ @Benchmark - public int testCallMulti1Poly2() { - swapMultiParts(); - return multi1a.getInt(); + public int test1stInt3Types() { + FirstInterface ai = as[l]; + l = ++ l % 3; + return ai.getIntFirst(); } - /** - * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different - * interfaces take different amounts of time (They do for hotspot) - */ @Benchmark - public int testCallMulti2Poly2() { - swapMultiParts(); - return multi1b.get1(); + public int test1stInt5Types() { + FirstInterface ai = as[l]; + l = ++ l % asLength; + return ai.getIntFirst(); } - /** Interface call with three different receivers */ @Benchmark - public void testCallPoly3(Blackhole bh) { - for (int kk = 0; kk < 3; kk++) { - bh.consume(as[kk].getInt()); - } + public int test2ndInt2Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = 1 - l; + return ai.getIntSecond(); } - /** Interface call with five different receivers. */ @Benchmark - public void testCallPoly5(Blackhole bh) { - for (int kk = 0; kk < 5; kk++) { - bh.consume(as[kk].getInt()); - } + public int test2ndInt3Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = ++ l % 3; + return ai.getIntSecond(); } - int l; - - /** - * Interface call address computation within loop but the receiver preexists the loop and the ac can be moved outside - * of the loop - */ @Benchmark - public int testAC1() { - AnInterface ai = as[l]; - l = 1 - l; - return ai.getInt(); + public int test2ndInt5Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = ++ l % asLength; + return ai.getIntSecond(); } - /** Tests an interface cast followed by an interface call. */ - @Benchmark - public int testInterfaceCastAndCall() throws Exception { - return ((AnInterface) dummy1).getInt() + ((AnInterface) dummy2).getInt() - + ((AnInterface) dummy3).getInt(); - } }